Hive - Varchar vs String,如果存储格式是 Parquet 文件格式有什么优势

Hive - Varchar vs String , Is there any advantage if the storage format is Parquet file format

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

我的table、VIN 号码(17 个字符)、状态(2 个字符)...等字段很少

所以我的问题是在 table 创建过程中,如果我选择使用 Varchar(X) 与 String,是否存在任何存储或性能问题,

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

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

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

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

就存储和性能而言,使用 string 而不是 varchar 需要付出多少代价

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

T我看到的唯一区别是 String 是无界的,最大值为 32,767 字节,而 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 方法 class 检查列的数据类型。即 varcharstring,因此它会为这些类型创建 writer class。

现在让我们继续 VarcharDataWriter class。

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));
    }
  }

StringDataWriterclass

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 两个 classes 中的方法实际上添加了编码数据类型(encodeUTF8 编码)的二进制值。并且字符串编码不同于 varchar 的编码。

问题简答:-字符串和varchar的unicode编码不同。在存储方面,它可能会根据编号略有不同。存储的字节数。但根据我的理解,性能方面,配置单元是 schema on read 工具。 ParquetRecordReader 知道如何读取记录。它只是读取 bytes.So 由于 varchar 或 string 数据类型,不会有任何性能差异。

鉴于 ORC 格式已成为 Hive 的默认标准,我的情况是限制和关注围绕 ORC 格式的讨论 storage.I 不要相信性能真的是 Hive 本身中 VARCHAR 和 STRING 之间的问题。对于 ORC 格式,两种情况下的数据编码(请参阅下面的 link)是相同的。这甚至在您使用自定义 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,因此点被否定。

感谢您纠正我,以防您发现理解有误。另外,可以提供一个可能有帮助的参考 link。