我有一个HIVE表,它将容纳数十亿条记录,它是一个时间序列数据,所以分区是每分钟。每分钟我们将有大约 100 万条记录。
我的表中有几个字段,VIN 号(17 个字符(,状态(2 个字符(...等
所以我的问题是在表创建过程中,如果我选择使用 Varchar(X( 与字符串,是否存在任何存储或性能问题,
瓦尔查尔的几个限制是 https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types#LanguageManualTypes-string
-
如果我们提供超过"x"个字符,它将静默截断,因此 保持字符串将是面向未来的。
-
非泛型 UDF 不能直接使用 varchar 类型作为输入参数 或返回值。可以改为创建字符串 UDF,并且 varchar 值将被转换为字符串并传递给 UDF。 要直接使用 varchar 参数或返回 varchar 值, 创建一个泛型 UDF。
-
可能还有其他上下文不支持 varchar,如果他们 依靠基于反射的方法来检索类型信息。 这包括一些 SerDe 实现。
-
在存储和性能方面,使用字符串而不是 varchar 需要支付的成本是多少
让我们尝试从 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方法实际上都添加了编码数据类型(编码UTF8编码(的二进制值。而对于字符串编码不同于瓦尔查尔的编码。
问题的简短回答:-字符串和 varchar 的 Unicode 编码是不同的。 存储方面,它可能根据编号而几乎没有变化。 存储的字节数。但根据我的理解,性能方面,蜂巢是schema on read
工具。ParquetRecordReader
知道如何阅读记录。它只读取字节。因此,不会因 varchar 或字符串数据类型而产生任何性能差异。
最好的方法是使用字符串。varchar 也在内部存储为字符串。如果确实要数据类型,请根据需要在相同数据的基础上创建视图。
我看到的唯一区别是字符串是无界的,最大值为 32,767 字节,而 Varchar 是有界的。字符串有效地限制数据(如果它不使用它(。
矢量化支持也可用于字符串。
我的情况是限制并将讨论重点放在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,因此点为否定。
感谢您纠正我,以防您发现理解不同。此外,可以提供可能会有所帮助的参考链接。