Hive不支持写入数据到Delta Lake和Hudi,但是可以通过外部表的方式查询Delta Lake和Hudi中的数据。本文通过示例为您介绍如何使用EMR上的Hive访问Delta Lake和Hudi数据。

前提条件

已创建Hadoop集群,详情请参见创建集群

使用限制

EMR-3.36.0及后续版本和EMR-5.2.0及后续版本,支持Hive对Hudi进行读操作。

Hive访问Delta Lake数据

  1. 进入Spark命令行。
    1. 使用SSH方式登录到集群主节点,详情请参见登录集群
    2. 执行以下命令,进入Spark命令行。
      spark-sql
  2. 在Spark中创建并查询表数据。
    1. 执行以下命令,在Spark中创建Delta表。
      create table delta_table (id int) using delta location "/tmp/delta_table";
    2. 执行以下命令,向表中插入数据。
      insert into delta_table values 0,1,2,3,4;
    3. 执行以下命令,查看表数据。
      select * from delta_table;
      返回包含如下的信息。
      2
      3
      4
      0
      1
      Time taken: 1.847 seconds, Fetched 5 row(s)
  3. 在Hive中查看Delta Lake数据。
    1. 执行以下命令,进入Hive命令行。
      hive
    2. 执行以下命令,在Hive中查看Delta Lake表。
      desc formatted delta_table;
      返回如下信息。
      OK
      # col_name              data_type               comment
      
      id                      int
      
      # Detailed Table Information
      Database:               default
      Owner:                  root
      CreateTime:             Sat Jul 24 14:20:44 CST 2021
      LastAccessTime:         UNKNOWN
      Retention:              0
      Location:               hdfs://emr-header-1.cluster-238095:9000/tmp/delta_table
      Table Type:             EXTERNAL_TABLE
      Table Parameters:
              EXTERNAL                TRUE
              delta.database          default
              delta.syncMetadataToCatalog     true
              delta.table             delta_table
              delta.tableType         EXTERNAL_TABLE
              last_modified_time      1627107644
              numFiles                0
              spark.sql.sources.provider      delta
              spark.sql.sources.schema.numParts       1
              spark.sql.sources.schema.part.0 {\"type\":\"struct\",\"fields\":[{\"name\":\"id\",\"type\":\"integer\",\"nullable\":true,\"metadata\":{}}]}
              totalSize               0
              transient_lastDdlTime   1627107644
      
      # Storage Information
      SerDe Library:          org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe
      InputFormat:            io.delta.hive.DeltaInputFormat
      OutputFormat:           io.delta.hive.DeltaOutputFormat
      Compressed:             No
      Num Buckets:            0
      Bucket Columns:         []
      Sort Columns:           []
      Storage Desc Params:
              path                    hdfs://emr-header-1.cluster-238095:9000/tmp/delta_table
              serialization.format    1
      Time taken: 1.09 seconds, Fetched: 37 row(s)                                  
    3. 执行以下命令,在Hive中查看Delta Lake表的数据。
      select * from delta_table;
      返回如下信息。
      OK
      2
      3
      4
      0
      1
      Time taken: 1.897 seconds, Fetched: 5 row(s)
      说明 查看数据与在Spark中插入的数据一致,说明Hive已经成功访问了Delta Lake的数据。

Hive访问Hudi数据

注意 EMR-3.36.0及后续版本和EMR-5.2.0及后续版本,支持Hive对Hudi进行读操作。
  1. 进入Spark命令行。
    1. 使用SSH方式登录到集群主节点,详情请参见登录集群
    2. 执行以下命令,进入Spark命令行。
      spark-sql --conf 'spark.serializer=org.apache.spark.serializer.KryoSerializer' \
      --conf 'spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension'
  2. 在Spark中创建并查询表数据。
    1. 执行以下命令,在Spark中创建Hudi表。
      create table h0 (
                     id bigint,
                     name string,
                     price double
                   ) using hudi;  
      您可以执行以下命令,查看表结构属性。
      desc formatted h0;
      返回信息中会多出以下字段,这些字段是Hudi的默认字段,会同步到元数据中。
      _hoodie_commit_time string  NULL
      _hoodie_commit_seqno  string  NULL
      _hoodie_record_key  string  NULL
      _hoodie_partition_path  string  NULL
      _hoodie_file_name string  NULL
    2. 执行以下命令,向表中插入数据。
      insert into h0 select 1, 'a1', 10;
    3. 执行以下命令,查询表数据。
      select * from h0;
      返回如下信息。
      OK
      SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
      SLF4J: Defaulting to no-operation (NOP) logger implementation
      SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
      20210728180336  20210728180336_0_1      74641e17-75d6-4243-be71-a5aa98b5c1af            49062904-52da-402c-82c1-84c04d3c2a4c-0_0-6-6_20210728180336.parquet     1       a1      10.0
      Time taken: 2.001 seconds, Fetched: 1 row(s)
  3. 在Hive中查看Hudi数据。
    1. 执行以下命令,进入Hive命令行。
      hive
    2. 执行以下命令,查询表数据。
      select * from h0;
      返回如下信息。
      OK
      SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
      SLF4J: Defaulting to no-operation (NOP) logger implementation
      SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
      20210728180336  20210728180336_0_1      74641e17-75d6-4243-be71-a5aa98b5c1af            49062904-52da-402c-82c1-84c04d3c2a4c-0_0-6-6_20210728180336.parquet     1       a1      10.0
      Time taken: 2.001 seconds, Fetched: 1 row(s)
      说明 查看的数据与在Spark中插入的数据一致,说明Hive已经成功访问了Hudi的数据。如果在Hive中不想看到Hudi的默认系统字段,可以在Hive中创建一个外表指向Hudi的目录。
      您也可以在Hive中查看Hudi表结构的信息。
      desc formatted h0;
      返回如下信息。
      OK
      # col_name              data_type             comment             
           
      _hoodie_commit_time   string                                    
      _hoodie_commit_seqno  string                                    
      _hoodie_record_key    string                                    
      _hoodie_partition_path  string                                    
      _hoodie_file_name     string                                    
      id                    bigint                                    
      name                  string                                    
      price                 double                                    
           
      # Detailed Table Information     
      Database:             default                
      Owner:                root                   
      CreateTime:           Thu Jun 24 16:50:48 CST 2021   
      LastAccessTime:       UNKNOWN                
      Retention:            0                      
      Location:             hdfs://emr-header-1.cluster-23****:9000/user/hive/warehouse/h0   
      Table Type:           MANAGED_TABLE          
      Table Parameters:    
        last_commit_time_sync 20210624165059      
        numFiles              1                   
        spark.sql.create.version  2.4.7               
        spark.sql.sources.provider  hudi                
        spark.sql.sources.schema.numParts 1                   
        spark.sql.sources.schema.part.0 {\"type\":\"struct\",\"fields\":[{\"name\":\"_hoodie_commit_time\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"_hoodie_commit_seqno\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"_hoodie_record_key\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"_hoodie_partition_path\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"_hoodie_file_name\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"id\",\"type\":\"long\",\"nullable\":true,\"metadata\":{}},{\"name\":\"name\",\"type\":\"string\",\"nullable\":true,\"metadata\":{}},{\"name\":\"price\",\"type\":\"double\",\"nullable\":true,\"metadata\":{}}]}
        totalSize             434752              
        transient_lastDdlTime 1624524648          
           
      # Storage Information    
      SerDe Library:        org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe  
      InputFormat:          org.apache.hudi.hadoop.HoodieParquetInputFormat  
      OutputFormat:         org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat   
      Compressed:           No                     
      Num Buckets:          -1                     
      Bucket Columns:       []                     
      Sort Columns:         []                     
      Storage Desc Params:     
        path                  hdfs://emr-header-1.cluster-234173:9000/user/hive/warehouse/h0
        serialization.format  1                   
      Time taken: 0.204 seconds, Fetched: 40 row(s)