首页 文章

Hive - Varchar vs String,如果存储格式是Parquet文件格式,是否有任何优势

提问于
浏览
2

我有一个HIVE表,它将保存数十亿条记录,它是一个时间序列数据,因此分区是每分钟 . 每分钟我们将有大约100万条记录 .

我桌上的字段很少,VIN号码(17个字符),状态(2个字符)......等等

所以我的问题是在表创建期间如果我选择使用Varchar(X)vs String,是否存在任何存储或性能问题,

varchar的几个限制是https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types#LanguageManualTypes-string

  • 如果我们提供的不仅仅是“x”字符,它将默默地截断,因此保持字符串将是未来的证据 .

  • 非泛型UDF不能直接使用varchar类型作为输入参数或返回值 . 可以创建字符串UDF,并将varchar值转换为字符串并传递给UDF . 要直接使用varchar参数或返回varchar值,请创建GenericUDF .

  • 如果它们依赖基于反射的方法来检索类型信息,则可能还有其他不支持varchar的上下文 . 这包括一些SerDe实现 .

在存储和性能方面,我需要为使用字符串而不是varchar付出多少代价

3 回答

  • 1

    我的情况是围绕ORC格式限制和集中讨论,因为它已成为Hive存储的默认标准 . 我不认为性能在Hive本身的VARCHAR和STRING之间确实存在问题 . 在涉及ORC格式的情况下,数据的编码(参见下面的链接)是相同的 . 这甚至在您使用自定义Serde时也适用,它全部被视为STRING,然后应用编码 .

    对我来说真正的问题将是STRING如何被其他第三方工具和编程语言使用 . 如果最终用途没有STRING的文档问题,那么使用STRING作为VARCHAR(n)类型的类型很容易 . 在使用需要通过管道映射元素的ETL时,这尤其有用,并且您不希望忽略忽略大小错误的风险 . 回到第三方工具,例如SAS在连接到Hive时有许多已记录的读取STRING类型的问题 . 它将成为一些人的痛苦领域,对于一些人来说,它将成为各自建筑的一个意识点 . 例如,通过JDBC或ODBC连接到Hive时的数据库可能会将数据读取为VARCHAR(max),这可能意味着需要考虑的挑战数量 .

    我建议将此视为一个主要因素,而不是Hive本身的表现 . 到目前为止,我还没有遇到过任何建议VARCHAR比STRING更好地决定要使用的类型 .

    https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC#LanguageManualORC-StringColumnSerialization

    另一点是VARCHAR现在支持矢量化 . 在任何情况下,接收VARCHAR的UDF将被视为STRING因此被取消 .

    感谢您纠正我,以防您发现理解不同 . 此外,可以提供可能有帮助的参考链接 .

  • 1

    最好的方法是使用String . varchar也在内部存储为字符串 . 如果您想明确数据类型,请根据需要在相同数据的基础上创建一个视图 .

    我看到的唯一区别是String是无界的,最大值为32,767字节,Varchar有界 . 如果数据不使用,则字符串会有效地限制数据 .

    矢量化支持也可用于String .

  • 3

    让我们试着理解它在API中的实现方式: -

    org.apache.hadoop.hive.ql.io.parquet.write.DataWritableWriter
    

    这是神奇的开始 - >

    private DataWriter createWriter(ObjectInspector inspector, Type type) {
    case stmt.....
    ........
    case STRING:
            return new StringDataWriter((StringObjectInspector)inspector);
        case VARCHAR:
            return new VarcharDataWriter((HiveVarcharObjectInspector)inspector);
    
    }
    

    DataWritableWriter的createWriter方法检查列的数据类型 . 即 varcharstring ,因此它为这些类型创建编写器类 .

    现在让我们继续前进到 VarcharDataWriter 类 .

    private class VarcharDataWriter implements DataWriter {
        private HiveVarcharObjectInspector inspector;
    
        public VarcharDataWriter(HiveVarcharObjectInspector inspector) {
          this.inspector = inspector;
        }
    
        @Override
        public void write(Object value) {
          String v = inspector.getPrimitiveJavaObject(value).getValue();
          recordConsumer.addBinary(Binary.fromString(v));
        }
      }
    

    OR

    StringDataWriter

    private class StringDataWriter implements DataWriter {
        private StringObjectInspector inspector;
    
        public StringDataWriter(StringObjectInspector inspector) {
          this.inspector = inspector;
        }
    
        @Override
        public void write(Object value) {
          String v = inspector.getPrimitiveJavaObject(value);
          recordConsumer.addBinary(Binary.fromString(v));
        }
      }
    

    两个类中的 addBinary 方法实际上都添加了编码数据类型的二进制值(encodeUTF8编码) . 并且对于字符串编码不同于varchar的编码 .

    short answer to question:- string和varchar的unicode编码不同 . 存储方面,它可能几乎没有变化 . 商店的字节数 . 但根据我的理解,性能明智,hive是 schema on read 工具 . ParquetRecordReader 知道如何阅读记录 . 它只读取字节 . 因为varchar或字符串数据类型不会有任何性能差异 .

相关问题