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

时间:2017-07-19 13:16:36

标签: hive hql parquet hcatalog

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

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

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

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

  1. 如果我们提供超过" x"字符会默默地截断,所以 保持字符串将是未来的证明。

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

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

  2. 在存储和性能方面使用字符串而不是varchar需要付出的代价是什么

3 个答案:

答案 0 :(得分:4)

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

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

矢量化支持也可用于String。

答案 1 :(得分:1)

让我们试着了解它在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));
    }
  }

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的编码。

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

答案 2 :(得分: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因此被否定。

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