我有一个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需要付出的代价是什么
答案 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方法检查列的数据类型。即varchar
或string
,因此它会为这些类型创建编写器类。
现在让我们继续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更好地决定要使用的类型。
另一点是VARCHAR现在支持矢量化。在任何情况下,接收VARCHAR的UDF将被视为STRING因此被否定。
感谢您纠正我,以防您发现不同的理解。此外,可以提供可能有帮助的参考链接。