学习 Presto(四):集成 Hive

Hive 简介

Apache Hive 主要由三部分组成:

  • 数据,存储在 HDFS 的文件集,文件格式为 CSV、 ORA、Avro 或者 Parquet 等
  • 元数据,保存在 MySQL 的表,记录了 Hive 表定义等元数据信息
  • 执行引擎,默认为 MapReduce,也支持 Apache Tez 和 Apache Spark 等

Presto 集成 Hive,只是使用了 Hive 的数据和元数据,所以并不支持 HQL

配置

创建文件 etc/catalog/hive.properties 文件:

connector.name=hive  
hive.metastore.uri=thrift://<HIVE_METASTORE>:9083  
hive.config.resources=/etc/hadoop/conf/core-site.xml,/etc/hadoop/conf/hdfs-site.xml  

① 参数 hive.metastore.uri 配置 Hive 元数据服务,用于查询 Hive 元数据信息

② 参数 hive.config.resources 配置 HDFS 配置文件位置,用于访问 HDFS 文件

问题一:无法读取 Parquet 文件

使用 Presto 查询 Hive 表,抛异常 com.facebook.presto.spi.PrestoException: Can not read value at 0 in block 0 in file hdfs

Presto 版本 0.166

Spark 版本 2.2.0

导致问题的原因是 Spark 写入到 Hive 表中的 Parquet 文件版本过高,导致 Presto 无法读取

解决办法:

在构建 SparkSession 时,添加配置 spark.sql.parquet.writeLegacyFormat,一个🌰:

SparkSession.builder()  
  .master("local")
  .appName(appName)
  .enableHiveSupport()
  .config("spark.sql.parquet.writeLegacyFormat", true) // ①
  .getOrCreate()

① 在 Spark 2.2 中,在写入 Parquet 时,会启动 Legacy 模式,从而可以兼容 Spark 1.4 及之前的版本

问题二:Presto 查询到错误的列

Presto 查询文件格式为 Parquet 的 Hive 表,查询其中一个字段却返回另一个字段的数据

Presto 版本 0.166

导致该问题的原因是查询 Hive 表 Schema 和底层 Parquet 数据文件 Schema 不一致导致的。改问题有两种解决方式:

  1. 修改 Hive 表 Schema 保持与底层 Parquet 数据文件 Schema 一致;
  2. 修改 Hive Catalog 配置文件,新增配置 hive.parquet.use-column-names=true

关于 hive.parquet.use-column-names 属性,官方的解释:

By default, columns in Parquet files are accessed by their ordinal position in the Hive table definition. To access columns based on the names recorded in the Parquet file, set hive.parquet.use-column-names=true in your Hive catalog properties file.

问题三:Hive 元数据缓存

有时 Hive 底层数据文件发生变化,由于 Presto 缓存了 Hive 元数据。禁用 Hive 元数据缓存,编辑 Hive 配置文件,添加以下配置:

hive.metastore-cache-ttl=0  
hive.metastore-refresh-interval=0  

参考