对Parquet文件的支持

    上级主题: 使用Hadoop分布式文件系统(HDFS)表

    Parquet文件格式被设计为利用Hadoop生态系统的项目中压缩的、高效的列式数据表示。Parquet支持复杂嵌套数据结构并且使用Dremel的record shredding and assembly算法。Parquet支持非常高效的压缩和编码方式。Parquet允许在列级别上指定压缩方式,并且支持增加更多自定义的编码方式。

    有关Parquet的信息,请见Parquet的文档。

    列式数据存储和Parquet文件格式的概述可见https://blog.twitter.com/2013/dremel-made-simple-with-parquet

    对Parquet文件格式的支持要求这些jar文件:

    • parquet-hadoop-1.7.0.jar
    • parquet-common-1.7.0.jar
    • parquet-encoding-1.7.0.jar
    • parquet-column-1.7.0.jar
    • parquet-generator-1.7.0.jar
    • parquet-format-2.3.0-incubating.jar

    注意:Cloudera 5.4.x Hadoop包括了一些Parquet的jar文件。不过,这些jar文件中的Java类名是parquet.xxx。gphdfs协议使用Java类名org.apache.parquet.xxx。可以下载使用org.apache.parquet这种类名的jar文件并且将其安装在Greenplum数据库主机上。

    gphdfs协议还支持使用parquet-hadoop-bundle-1.7.0.jar,它含有在Hadoop环境中使用Parquet所需的类。不支持这些版本的parquet-hadoop-bundle:

    • 版本 1.6 及更早的版本。这些版本用的不是org.apache.parquet这样的Java类名。
    • 版本 1.8 及其后的版本。这些版本包含gphdfs不支持的类VersionParser。

    关于下载Parquet的jar文件的信息,请见

    在Greenplum数据库的所有主机上,确保安装了这些jar文件并且它们都在gphdfs协议所使用的classpath上。classpath由shell脚本$GPHOME/lib/hadoop/hadoop_env.sh指定。作为一个Hadoop 2的例子,用户可以把那些jar文件安装在$HADOOP_HOME/share/hadoop/common/lib中。hadoop_env.sh脚本文件会把那些jar文件加入到classpath。

    例如,如果目录$HADOOP_HOME/share/hadoop/common/lib不存在,作为gpadmin用户在Greenplum数据库的所有主机上创建该目录。然后在所有主机上把这些jar文件加到该目录中。

    hadoop_env.sh脚本文件会为gphdfs协议把那些jar文件增加到classpath。该脚本文件中是这个片段负责这项工作:

    Greenplum数据库的gphdfs协议支持版本1或2的Parquet文件格式。Parquet利用了HDFS上压缩的列式数据表示。在一个Parquet文件中,包含数据结构信息的元数据(Parquet模式定义)被写在数据之后以允许单趟写。

    这是一个Parquet模式定义格式的例子:

    1. repeated byte_array binary_field;
    2. required int32 int32_field;
    3. optional int64 int64_field;
    4. required boolean boolean_field;
    5. required fixed_len_byte_array(3) flba_field;
    6. required byte_array someDay (utf8);
    7. };

    The definition for last field 最后一个域someDay的定义指定了带有utf8标注的binary数据类型。该数据类型和标注定义该数据是一种UTF-8编码的字符串。

    1. CREATE EXTERNAL TABLE tablename (column_spec) LOCATION ( 'gphdfs://location') FORMAT 'PARQUET'

    location可以是一个Parquet文件或者含有一组Parquet文件的一个目录。对于文件名可以使用通配符字符 * 来匹配任意多个字符。如果在读取Parquet文件时该位置指定的是多个文件,Greenplum数据库会使用第一个文件中的模式作为读取其他文件的模式。

    下面的表格列出了Greenplum如何在Parquet模式定义没有包含标注时转换Parquet数据类型。

    注意: 在把Parquet的int数据类型读取为Greenplum数据库的smallint数据类型时,必须确保Parquet的int值不会超过Greenplum数据库的最大smallint值。如果Parquet值太大,Greenplum数据库的值将不准确。

    gphdfs协议为这些情况考虑Parquet的模式标注。对其他情况,数据转换基于Parquet模式的简单类型进行:

    注意: 在指定decimal、date、interval或者 time*标注时,请参考限制和注解以及Parquet文档。

    如果Parquet域类型是不带任何标注的binary,gphdfs协议把该域的数据转换成文本,并且对应的Greenplum数据库外部表列的数据类型被定义为text。

    在读取Parquet的类型group时,gphdfs协议把group数据转换成一个XML文档。

    这个模式包含一个名称为inner的required group。

    1. message test {
    2. required byte_array binary_field;
    3. required int64 int64_field;
    4. int32 age;
    5. required boolean test;
    6. required byte_array name (UTF8);
    7. }
    8. };

    这里是group数据的一个单一行怎样被转换成XML的。

    这个模式的例子包含一个名称为inner的repeated group。

    1. message test {
    2. required byte_array binary_field;
    3. repeated group inner {
    4. int32 age;
    5. required boolean test;
    6. required byte_array name (UTF8);
    7. }
    8. };

    对于一个repeated group,Parquet文件可以在一个行中包含多组group数据。对于这个模式的例子,inner group的数据被转换成XML数据。

    这是Parquet文件中的数据包含两组inner group数据时的输出实例。

    1. <inner type="repeated">
    2. <inner type="group">
    3. <age type="int">50</age>
    4. <test type="boolean">true</test>
    5. <name type="string">fred</name>
    6. </inner>
    7. <inner>
    8. <age type="int">23</age>
    9. <test type="boolean">false</test>
    10. <name type="string">sam</name>
    11. </inner>
    12. </inner>

    Apache Hive数据仓库软件可以管理和查询位于分布式存储中的大型数据集。有关Apache Hive所使用的Parquet的信息请见。

    对于存储在Parquet文件中的Hive 1.1数据,这个表格列出了Greenplum数据库如何转换该数据。该转换基于Hive生成的Parquet模式进行。有关Hive生成的Parquet模式的信息请见对Hive生成的Parquet模式的注解

    对Hive生成的Parquet模式的注解

      1. CREATE TABLE hpSimple(c1 tinyint, c2 smallint, c3 int, c4 bigint,

      这是hpSimple表数据的Hive生成的Parquet模式。

      gphdfs协议把Parquet的整数数据类型转换成Greenplum数据库的数据类型int。

    • 对于Hive的char数据类型,Greenplum数据库的列数据类型可以是text或者char。对于Hive的varchar数据类型,Greenplum数据库的列数据类型可以是text或者varchar。

    • 基于Hive生成的Parquet模式,一些Hive数据被转换成Greenplum数据库的XML数据。例如,存储在一个Parquet文件中的Hive数组列数据会被转换成XML数据。例如,这是一个类型为array[int]的Hive列的Hive生成的Parquet模式。

      1. optional group col1 (LIST) {
      2. repeated group bag {
      3. optional int32 array_element;
      4. }
      5. }

      gphdfs协议把Parquet的group数据转换成Greenplum数据库的数据类型XML。

    • 对于Hive的timestamp数据类型,该数据类型的Hive生成的Parquet模式指定数据被作为数据类型int96存储。gphdfs协议把int96数据类型转换为Greenplum数据库的bytea数据类型。

    对于可写的外部表,用户可以在location中指定的文件后面加上参数。可以用以?开始并且域/值对由&分隔的http查询字符串语法增加参数。

    注意:

    1. 创建一个内部字典。如果文本列包含相似或者重复数据,启用一个字典能够提升Parquet文件的压缩。

    在写一个Parquet文件时,gphdfs协议可以基于表定义生成一个Parquet模式。

    • 表名被用作Parquet的message名称。
    • 列名被用作Parquet的域名称。

    在从一个Greenplum数据库表定义创建Parquet模式时,模式基于列的数据类型生成。

    注意: 要支持Null数据,在创建一个Parquet模式时用gphdfs协议指定Parquet的optional模式标注。

    一个Greenplum数据库表定义和gphdfs协议生成的Parquet模式的简单例子。

    一个Parquet文件的外部表定义例子。

    1. CREATE WRITABLE EXTERNAL TABLE films (
    2. code char(5),
    3. title varchar(40),
    4. id integer,
    5. date_prod date,
    6. subtitle boolean
    7. ) LOCATION ( 'gphdfs://my-films') FORMAT 'PARQUET' ;
    1. message films {
    2. optional byte_array code;
    3. optional byte_array title (utf8);
    4. optional int32 id;
    5. optional binary date_prod (utf8);
    6. optional boolean subtitle;
    • 对于可写的外部表,Greenplum数据库外部表的列定义不能指定NOT NULL来支持自动生成一个Parquet模式。当gphdfs协议自动生成一个Parquet模式时,gphdfs协议会指定域属性optional来支持Parquet模式中的null。在Parquet中repeated域可以是null。
    • gphdfs协议只为可读的外部表支持Parquet的嵌套group结构。嵌套结构会被转换成一个XML文档。
    • Greenplum数据库没有一种无符号的int数据类型。Greenplum数据库会把Parquet的无符号int数据类型转换为下一种最大的Greenplum数据库int类型。例如,Parquet的uint_8会被转换成Greenplum数据库的int(32位)。
    • Greenplum数据库支持任何UDT数据类型或者UDT数组数据类型。Greenplum会尝试把UDT转换成一个字符串。如果该UDT不能被转换为一个字符串,Greenplum数据库会返回一个错误。
    • Parquet中的Date数据类型从1970.1.1开始,而Greenplum数据库中的Date从4173 BC开始,由于最大值不同所以Greenplum数据库不能转换date数据类型。同样的情况发生在Parquet中的Timestamp_millis和Greenplum数据库中的Timestamp之间。