Hive Catalog
通过连接 Hive Metastore,或者兼容 Hive Metatore 的元数据服务,Doris 可以自动获取 Hive 的库表信息,并进行数据查询。
除了 Hive 外,很多其他系统也会使用 Hive Metastore 存储元数据。所以通过 Hive Catalog,我们不仅能访问 Hive 表,也能访问使用 Hive Metastore 作为元数据存储的其他表格式,如 Iceberg、Hudi 等。
适用场景
| 场景 | 说明 |
|---|---|
| 查询加速 | 利用 Doris 分布式计算引擎,直接访问 Hive 数据进行查询加速。 |
| 数据集成 | 读取 Hive 数据并写入到 Doris 内表。或通过 Doris 计算引擎进行 ZeroETL 操作。 |
| 数据写回 | 将任意 Doris 支持读取的数据源数据进行加工后,写回到 Hive 表存储。 |
配置 Catalog
语法
CREATE CATALOG [IF NOT EXISTS] catalog_name PROPERTIES (
'type'='hms', -- required
'hive.metastore.type' = '<hive_metastore_type>', -- optional
'hive.version' = '<hive_version>', -- optional
'fs.defaultFS' = '<fs_defaultfs>', -- 写入必填,只读时可选
{MetaStoreProperties},
{StorageProperties},
{HiveProperties},
{CommonProperties}
);
-
<hive_metastore_type>指定 Hive Metastore 的类型。
-
hms:标准的 Hive Metastore 服务。 -
glue:使用 Hive Metastore 兼容接口访问 AWS Glue 元数据服务。 -
dlf:使用 Hive Metastore 兼容接口访问阿里云 DLF 元数据服务。
-
-
<fs_defaultfs>当需要通过 Doris 写入数据到这个 Hive Catalog 中表时,此参数为必选项。示例:
'fs.defaultFS' = 'hdfs://namenode:port' -
{MetaStoreProperties}MetaStoreProperties 部分用于填写 Metastore 元数据服务连接和认证信息。具体可参阅【支持的元数据服务】部分。
-
{StorageProperties}StorageProperties 部分用于填写存储系统相关的连接和认证信息。具体可参阅【支持的存储系统】部分。
-
{HiveProperties}HiveProperties 部分用于填写和 Hive Catalog 相关的其他参数。
-
get_schema_from_table:默认为 false。默认情况下,Doris 会从 Hive Metastore 中获取表的 Schema 信息。但某些情况下可能出现兼容问题,如错误Storage schema reading not supported。此时可以将这个参数设置为 true,则会从 Table 对象中直接获取表 Schema。但注意,该方式会导致列的默认值信息被忽略。该参数自 2.1.10 和 3.0.6 版本支持。 -
hive.recursive_directories:在 list 分区目录时,是否递归子目录。该参数自 3.0.2 版本支持。在 4.0 版本之前,该参数默认值为false,之后的版本,该默认值为true。某些 Hive 外表的分区路径可能和表结构中的分区信息不匹配,需要将这个参数设为true以便获取子目录下的数据文件。 -
hive.ignore_absent_partitions:是否忽略不存在的分区。默认为true。如果设为false,当遇到不存在的分区时,查询会报错。该参数自 3.0.2 版本支持。 -
hive.staging_dir:用于设置 Hive 写操作的临时 staging 根目录。写入过程中数据会先写入该目录,写入完成后再移动到最终的 Hive 表目录。该路径可以是相对于 Hive 表根目录的相对路径,也可以是绝对路径。默认值为/tmp/.doris_staging。某些情况下,写入 Hive 表时会遇到/tmp目录和表目录分属不同 namespace,导致无法写入的问题,此时可以通过修改此参数,使用相对路径解决该问题。该参数自 4.0.3 版本开始支持。 -
hive.parquet.time-zone:FileScannerV2 读取 Hive 表时,用于还原旧版 ParquetINT96时间戳的兼容时区。默认值为空,此时 Doris 保留INT96中存储的日期和时间字段,不做时区转换。仅当 Catalog 中的INT96文件由写入端按已知时区进行过归一化时,才需要设置此属性。Hudi 表会有意忽略该属性,并保留现有的 SQL 会话时区行为。详情请参阅 Parquet INT96 时间戳兼容性。
-
-
{CommonProperties}CommonProperties 部分用于填写通用属性。请参阅 数据目录概述 中【通用属性】部分。
元数据缓存
为了提升访问外部数据源的性能,Apache Doris 会缓存 Hive 的元数据,包括表对象、分区名、分区对象、列统计信息、文件列表以及派生的分区裁剪结构。
Doris 4.1.x 之前的版本,元数据缓存主要由 FE 配置项全局控制,详见元数据缓存。
自 Doris 4.1.x 起,Hive Catalog 的外表元数据缓存使用统一的 meta.cache.* 键配置。下文的模块描述当前版本;Doris 4.1.x 和 4.2.x 的模块集合与此不同,见本页的 4.x 版本。
缓存属性配置
每个缓存模块使用统一的配置键格式:meta.cache.<engine>.<entry>.{enable,ttl-second,capacity,max-weight}。Hive 的 <engine> 为 hive。包含 Iceberg 表的 Hive Metastore Catalog 还会使用 Iceberg Catalog 中描述的 iceberg 模块。
| 属性 | 示例 | 含义 |
|---|---|---|
enable | true/false | 是否开启该缓存模块。 |
ttl-second | 600、0、-1 | 0 表示关闭该模块(立即生效,可用于查看最新数据);-1 表示永不过期;其他正整数表示按访问时间计算的 TTL 秒数。 |
capacity | 10000 | 缓存条目数上限。0 表示关闭该模块。 |
max-weight | 1GB | 自 Doris 4.1.4 起支持。可选的模块估算保留内存上限。必须为正数,0 会被拒绝。只有下表标注的模块接受该属性。 |
生效逻辑: 模块在 enable=true、ttl-second != 0 且 capacity > 0 时生效。FE 总上限、Catalog 上限或模块上限存在时,还会按估算内存控制准入,详见 外表元数据缓存内存管理。
缓存模块
Hive Catalog 包含以下缓存模块,全部接受 max-weight。
模块(<entry>) | 属性键前缀 | ENTRY_NAME | 缓存内容与影响 | 默认 enable / TTL / capacity |
|---|---|---|---|---|
table | meta.cache.hive.table. | hive-table | Hive Metastore 中的表对象。影响:减少规划阶段访问 Metastore 的次数。 | true / 86400 秒 / 10000 |
partition_names | meta.cache.hive.partition_names. | hive-partition-names | 分区名列表。影响:分区枚举;关闭后可实时看到新分区。 | true / 86400 秒 / 10000 |
partition | meta.cache.hive.partition. | hive-partition | 分区对象,例如 Location 和输入格式。 | true / 86400 秒 / 100000 |
column_stats | meta.cache.hive.column_stats. | hive-column-stats | Hive Metastore 中的列统计信息。 | true / 86400 秒 / 10000 |
file | meta.cache.hive.file. | hive-file | 文件列表。影响:减少远端 LIST 操作;关闭后可实时看到文件变化。 | true / 86400 秒 / 10000 |
partition_view | meta.cache.hive.partition_view. | hive-partition-view | 由分区名派生的分区裁剪结构。 | true / 86400 秒 / 1000 |
Hive 表的列结构由所有外表 Catalog 共享的 default 引擎缓存(meta.cache.default.schema.*)。
旧参数映射与转换
推荐使用统一键。以下旧 Catalog 属性仍然可用,并按下表映射:
| 旧属性键 | 统一键 | 说明 |
|---|---|---|
schema.cache.ttl-second | meta.cache.default.schema.ttl-second 和 meta.cache.hive.table.ttl-second | 表结构缓存和表对象缓存的过期时间 |
partition.cache.ttl-second | meta.cache.hive.partition_names.ttl-second | 分区名列表的过期时间 |
file.meta.cache.ttl-second | meta.cache.hive.file.ttl-second | 文件列表的过期时间 |
最佳实践
- 实时访问最新数据:希望每次查询都看到外部数据源最新的分区或文件变化时,将对应模块的
ttl-second设为0。-- 关闭文件列表缓存,实时看到文件变化
ALTER CATALOG hive_ctl SET PROPERTIES ("meta.cache.hive.file.ttl-second" = "0");
-- 关闭分区名缓存,实时看到新分区
ALTER CATALOG hive_ctl SET PROPERTIES ("meta.cache.hive.partition_names.ttl-second" = "0"); - 性能优化:元数据变化不频繁的场景,可适当增大
capacity和ttl-second,减少对 Hive Metastore 和文件系统的访问压力。对超大表可用max-weight限制文件列表和分区裁剪缓存的内存。
Catalog 属性修改成功后,受影响的元数据缓存会被丢弃,并在下一次访问时按新配置重建。修改 meta.cache.max-weight 或 schema.cache.ttl-second 会丢弃该 Catalog 的全部缓存;修改 meta.cache.<engine>.<entry>.* 只丢弃对应引擎的缓存。正在执行的查询不受影响。
可观测性
可以通过 information_schema.catalog_meta_cache_statistics 系统表观察缓存指标。ENTRY_NAME 显示上表中列出的名称,default 引擎的行是所有 Catalog 共享的表结构缓存:
SELECT engine_name, entry_name,
effective_enabled, ttl_second, capacity,
estimated_size, hit_rate, max_weight, estimated_weight
FROM information_schema.catalog_meta_cache_statistics
WHERE catalog_name = 'hive_ctl'
ORDER BY engine_name, entry_name;
系统表说明请参阅 catalog_meta_cache_statistics。
支持的 Hive 版本
支持 Hive 1.x,2.x,3.x,4.x。
其中 Hive 事务表支持 3.x 之后的版本,详情参阅【Hive 事务表】章节。
支持的元数据服务
注意:不同 Doris 版本所支持的服务类型和参数略有区别,请参考【基础示例】章节。
Hive Catalog 功能支持矩阵
| 元数据服务 | 表查询 | 视图查询 | DDL 操作 | 数据写回 |
|---|---|---|---|---|
| Hive | ✅ | ✅ | ✅ | ✅ |
| AWS Glue | ✅ | ✅ | ❌ | ❌ |
| DLF | ✅ | ✅ | ✅ | ✅ |
支持的存储系统
-
Apache Ozone(自 4.0.4 起支持)
如果需要通过 Doris 创建 Hive 表并写入数据,需要在 Catalog 属性中显式增加
fs.defaultFS属性。如果创建 Catalog 仅用于查询,则该参数可以省略。不同 Doris 版本所支持的服务类型和参数略有区别,请参考【基础示例】章节。
支持的数据格式
Parquet INT96 时间戳兼容性
Hive 表中的时间戳文件可能由不同引擎生成。是否需要时区转换取决于物理编码和写入端行为。Parquet INT96 本身不包含时区标注,因此 Doris 不会根据 INT96 值推断写入端时区。
自 4.1.5 版本起,hive.parquet.time-zone 接受 IANA 时区或 -12:00 至 +14:00 的 UTC 偏移,接受 UTC / GMT,拒绝 CST / PRC 等短别名。详见 Parquet。
Parquet INT96 时间戳
FileScannerV2 按以下规则处理 Parquet 时间戳:
| 物理编码 | 默认行为 | hive.parquet.time-zone 的作用 |
|---|---|---|
映射到 DATETIMEV2 的 INT96 | 保留文件中存储的日期和时间字段,SQL 会话时区不会使该值发生偏移。 | 将原始 INT96 值视为 UTC 时刻,再转换到配置的兼容时区,从而还原被旧版写入端归一化过的时间戳。 |
带时间戳逻辑类型的 INT64 | 遵循 Parquet 逻辑类型语义。 | 不受影响。 |
例如,假设预期的本地时间戳是 Asia/Shanghai 时区的 2021-01-01 10:11:00:
- 如果文件直接存储墙上时间字段
10:11:00,请不要设置hive.parquet.time-zone。即使 SQL 会话使用Asia/Shanghai,Doris 仍返回10:11:00。 - 如果旧版写入端先将该值归一化为 UTC 再写入
INT96,文件中可能存储02:11:00。将hive.parquet.time-zone设置为Asia/Shanghai后,Doris 会还原出10:11:00。
创建 Catalog 时配置兼容时区:
CREATE CATALOG hive_legacy_int96 PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9083',
'hive.parquet.time-zone' = 'Asia/Shanghai'
);
该值可以是 Asia/Shanghai 等 IANA 时区名称,也可以是 -12:00 到 +14:00 范围内的 UTC 偏移。非法值会导致 Catalog 创建失败。
hive.parquet.time-zone 作用于该 Catalog 中所有 Hive 表内映射到 DATETIMEV2 的 INT96 时间戳列。该属性不影响同一 Hive Metastore 中的 Iceberg 表,因为 Iceberg 定义了自己的时间戳语义。Hudi 也会有意忽略该属性:原生 base file 扫描和 JNI merge-on-read 扫描都保留变更前的行为,使用 SQL 会话时区解释时间戳。Parquet 元数据无法可靠地告诉 Doris 某个 INT96 写入端使用了哪种约定。不要仅为了匹配 SQL 会话时区而设置此属性。如果同一个 Hive Metastore 中的 Hive 表包含使用不同约定写入的 INT96 文件,应尽量通过不同 Catalog 分别访问。
读取 Parquet 文件的文件表值函数也接受同名属性。该兼容转换仅影响 FileScannerV2 对 Parquet INT96 的解码。FileScannerV1 有意保持不变,可能返回不同结果;切换到 FileScannerV1 不是本次变更的兼容方案。Parquet INT64 逻辑时间戳不受影响。INT96 列映射到 TIMESTAMPTZ 时,Doris 会忽略该属性并保留 UTC 时刻;该值的显示仍遵循 TIMESTAMPTZ 和会话时区语义。
迁移建议
- Doris 默认写入带逻辑类型的 Parquet
INT64时间戳。仅当 Hive 2、Hive 3 等旧版读取端要求INT96时,才设置enable_int96_timestamps = true。 - 升级到采用此 FileScannerV2 行为的版本前,请先检查现有 Hive 表。包含由旧版写入端归一化过的
INT96文件时,升级后返回的墙上时间可能发生变化。请比对有代表性的已知值,并在需要转换时将hive.parquet.time-zone设置为写入端时区。Hudi 保留现有的会话时区行为,因此不需要针对本次变更执行迁移。 - 设置
hive.parquet.time-zone前,请检查有代表性的文件并与已知时间戳值进行比对。不必要的配置反而会产生原本希望消除的时间偏移。 - 对使用不同
INT96写入约定的文件,使用不同 Catalog 分别访问,或将文件重写为统一的INT64编码。 - Doris 通过
enable_int96_timestamps = true显式导出INT96时,会使用导出会话时区归一化时间戳。通过 FileScannerV2 读回该文件时,请将hive.parquet.time-zone设置为相同的导出会话时区。详情请参阅数据导出概述。
列类型映射
请参阅Hive 与 Doris 数据类型映射,了解 Doris 4.2 的完整映射表、精度和不支持的类型。
基础示例
Hive Metastore
3.1+ 版本
- HDFS
- ViewFs
- S3
- OSS
- COS
- OBS
- GCS
- Azure Blob
- Ozone
- MinIO
访问未开启 Kerberos 认证的 HMS 和 HDFS 服务
CREATE CATALOG hive_hms_hdfs_test_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'fs.defaultFS' = 'hdfs://127.0.0.1:8520',
'hadoop.username' = 'doris'
);
访问开启 Kerberos 认证的 HMS 和 HDFS 服务
CREATE CATALOG hive_hms_hdfs_kerberos_test_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9583',
'hive.metastore.client.principal' = 'hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hive.metastore.client.keytab' = '/keytabs/hive-presto-master.keytab',
'hive.metastore.service.principal' = 'hive/hadoop-master@LABS.TERADATA.COM',
'hive.metastore.sasl.enabled' = 'true',
'hive.metastore.authentication.type' = 'kerberos',
'fs.defaultFS' = 'hdfs://127.0.0.1:8520',
'hadoop.security.auth_to_local' = 'RULE:[2:\$1@\$0](.*@LABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERLABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERREALM.COM)s/@.*//
DEFAULT',
'hadoop.security.authentication' = 'kerberos',
'hadoop.kerberos.principal' = 'hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hadoop.kerberos.keytab' = '/keytabs/hive-presto-master.keytab'
);
CREATE CATALOG hive_viewfs PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://172.0.0.1:9083',
'fs.defaultFS' = 'viewfs://your-cluster',
'fs.viewfs.mounttable.your-cluster.link./ns1' = 'hdfs://your-nameservice/',
'fs.viewfs.mounttable.your-cluster.homedir' = '/ns1',
'dfs.nameservices' = 'your-nameservice',
'dfs.ha.namenodes.your-nameservice' = 'nn1,nn2',
'dfs.namenode.rpc-address.your-nameservice.nn1' = '172.21.0.2:8088',
'dfs.namenode.rpc-address.your-nameservice.nn2' = '172.21.0.3:8088',
'dfs.client.failover.proxy.provider.your-nameservice' = 'org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider'
);
访问未开启 Kerberos 认证的 HMS
CREATE CATALOG hive_hms_s3_test_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
's3.region' = 'ap-east-1',
's3.access_key' = '<ak>',
's3.secret_key' = '<sk>'
);
使用 IAM Assumed Role 的方式获取 S3 访问凭证 (3.1.2+)
CREATE CATALOG hive_hms_on_s3_iamrole PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
's3.region' = 'us-east-1',
's3.role_arn' = 'arn:aws:iam::543815668950:role/role'
);
访问未开启 Kerberos 认证的 HMS
CREATE CATALOG hive_hms_on_oss_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'oss.region' = 'cn-beijing',
'oss.endpoint' = 'oss-cn-beijing.aliyuncs.com',
'oss.access_key' = '<ak>',
'oss.secret_key' = '<sk>'
);
访问开启 Kerberos 认证的 HMS
CREATE CATALOG hive_hms_on_oss_kerberos_old_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9583',
'hive.metastore.client.principal' = 'hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hive.metastore.client.keytab' = '/keytabs/hive-presto-master.keytab',
'hive.metastore.service.principal' = 'hive/hadoop-master@LABS.TERADATA.COM',
'hive.metastore.sasl.enabled' = 'true',
'hive.metastore.authentication.type' = 'kerberos',
'hadoop.security.auth_to_local' = 'RULE:[2:\$1@\$0](.*@LABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERLABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERREALM.COM)s/@.*//
DEFAULT',
'oss.region' = 'cn-beijing',
'oss.endpoint' = 'oss-cn-beijing.aliyuncs.com',
'oss.access_key' = '<ak>',
'oss.secret_key' = '<sk>'
);
访问未开启 Kerberos 认证的 HMS
CREATE CATALOG hive_hms_cos_test_region_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'cos.region' = 'ap-beijing',
'cos.endpoint' = 'cos.ap-beijing.myqcloud.com',
'cos.access_key' = '<ak>',
'cos.secret_key' = '<sk>'
);
访问开启 Kerberos 认证的 HMS
CREATE CATALOG hive_hms_on_cos_kerberos_new_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9583',
'hive.metastore.client.principal' = 'hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hive.metastore.client.keytab' = '/keytabs/hive-presto-master.keytab',
'hive.metastore.service.principal' = 'hive/hadoop-master@LABS.TERADATA.COM',
'hive.metastore.sasl.enabled' = 'true',
'hive.metastore.authentication.type' = 'kerberos',
'hadoop.security.auth_to_local' = 'RULE:[2:\$1@\$0](.*@LABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERLABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERREALM.COM)s/@.*//
DEFAULT',
'cos.region' = 'ap-beijing',
'cos.endpoint' = 'cos.ap-beijing.myqcloud.com',
'cos.access_key' = '<ak>',
'cos.secret_key' = '<sk>'
);
访问未开启 Kerberos 认证的 HMS
CREATE CATALOG test_hive_on_hms_obs_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'obs.region' = 'cn-north-4',
'obs.endpoint' = 'obs.cn-north-4.myhuaweicloud.com',
'cos.access_key' = '<ak>',
'cos.secret_key' = '<sk>'
);
访问开启 Kerberos 认证的 HMS
CREATE CATALOG hive_hms_on_obs_kerberos_new_catalog PROPERTIES (
'type' = 'hms',
'iceberg.catalog.type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9583',
'hive.metastore.service.principal' = 'hive/hadoop-master@LABS.TERADATA.COM',
'hive.metastore.sasl.enabled' = 'true',
'hive.metastore.client.principal' = 'hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hive.metastore.client.keytab' = '/keytabs/hive-presto-master.keytab',
'hive.metastore.authentication.type' = 'kerberos',
'hadoop.security.auth_to_local' = 'RULE:[2:\$1@\$0](.*@LABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERLABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERREALM.COM)s/@.*//
DEFAULT',
'obs.region' = 'cn-north-4',
'obs.endpoint' = 'obs.cn-north-4.myhuaweicloud.com',
'obs.access_key' = '<ak>',
'obs.secret_key' = '<sk>'
);
访问未开启 Kerberos 认证的 HMS
CREATE CATALOG `hive_hms_on_gcs_new_catalog` PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'gs.access_key' = '<ak>',
'gs.secret_key' = '<sk>',
'fs.gcs.support'='true'
);
Supported since 3.1.3
CREATE CATALOG `hive_hms_on_azure_blob_new_catalog` PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'azure.account_name' = '<account_name>',
'azure.account_key' = '<account_key>',
'azure.endpoint' = 'https://<account_name>.blob.core.windows.net',
'fs.azure.support'='true'
);
自 4.0.4 起支持
CREATE CATALOG `hive_hms_on_ozone_new_catalog` PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'fs.ozone.support' = 'true',
'ozone.endpoint' = 'http://ozone-s3g:9878',
'ozone.access_key' = '<ak>',
'ozone.secret_key' = '<sk>',
'ozone.region' = 'us-east-1',
'ozone.use_path_style' = 'true'
);
CREATE CATALOG test_hive_on_hms_minio_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'fs.minio.support' = 'true',
'minio.use_path_style' = 'true',
'minio.endpoint' = 'http://127.0.0.1:19001',
'minio.access_key' = '<ak>',
'minio.secret_key' = '<sk>'
);
2.1 & 3.0 版本
- HDFS
- S3
- OSS
- COS
- OBS
- GCS
- MinIO
访问未开启 Kerberos 认证的 HMS
CREATE CATALOG hive_hms_hdfs_test_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'hadoop.username' = 'doris',
'fs.defaultFS' = 'hdfs://127.0.0.1:8320'
);
访问开启 Kerberos 认证的 HMS
CREATE CATALOG test_two_hive_kerberos PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9583',
'hive.metastore.sasl.enabled' = 'true',
'hive.metastore.kerberos.principal' = 'hive/hadoop-master@LABS.TERADATA.COM',
'fs.defaultFS' = 'hdfs://127.0.0.1:8520',
'hadoop.kerberos.min.seconds.before.relogin' = '5',
'hadoop.security.authentication' = 'kerberos',
'hadoop.kerberos.principal' = 'hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hadoop.kerberos.keytab' = '/keytabs/hive-presto-master.keytab',
'hadoop.security.auth_to_local' = 'RULE:[2:\$1@\$0](.*@LABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERLABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERREALM.COM)s/@.*//
DEFAULT'
);
CREATE CATALOG hms_on_s3_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
's3.region' = 'ap-east-1',
's3.endpoint' = 'https://s3.ap-east-1.amazonaws.com',
's3.access_key' = '<ak>',
's3.secret_key' = '<sk>'
);
CREATE CATALOG hive_hms_on_oss_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'oss.region' = 'cn-beijing',
'oss.endpoint' = 'oss-cn-beijing.aliyuncs.com',
'oss.access_key' = '<ak>',
'oss.secret_key' = '<sk>'
);
CREATE CATALOG hive_hms_cos_test_region_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'cos.region' = 'ap-beijing',
'cos.endpoint' = 'cos.ap-beijing.myqcloud.com',
'cos.access_key' = '<ak>',
'cos.secret_key' = '<sk>'
);
CREATE CATALOG test_hive_on_hms_obs_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'obs.region' = 'cn-north-4',
'obs.endpoint' = 'obs.cn-north-4.myhuaweicloud.com',
'obs.access_key' = '<ak>',
'obs.secret_key' = '<sk>'
);
CREATE CATALOG hive_hms_on_gcs_s3 PROPERTIES (
'type'='hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'warehouse' = 's3://bucket/gcs/paimon_warehouse',
'gs.access_key' = '<ak>',
'gs.secret_key' = '<sk>',
'gs.endpoint' = 'storage.googleapis.com'
);
CREATE CATALOG test_hive_on_hms_minio_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
's3.endpoint' = 'http://127.0.0.1:19000',
's3.access_key' = '<ak>',
's3.secret_key' = '<sk>',
's3.path.style.access' = 'true'
);
AWS Glue
3.1+ 版本
- S3
AWS Glue 和 S3 存储服务共用一套认证信息。
CREATE CATALOG hive_glue_on_s3_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.type' = 'glue',
'glue.region' = 'ap-east-1',
'glue.endpoint' = 'https://glue.ap-east-1.amazonaws.com',
'glue.access_key' = '<ak>',
'glue.secret_key' = '<sk>'
);
Glue 服务的认证信息和 S3 的认证信息不一致时,可以通过以下方式单独指定 S3 的认证信息。
CREATE CATALOG hive_glue_on_s3_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.type' = 'glue',
'glue.region' = 'ap-east-1',
'glue.endpoint' = 'https://glue.ap-east-1.amazonaws.com',
'glue.access_key' = '<ak>',
'glue.secret_key' = '<sk>',
's3.region' = 'ap-east-1',
's3.endpoint' = 'https://s3.ap-east-1.amazonaws.com/',
's3.access_key' = '<ak>',
's3.secret_key' = '<sk>'
);
使用 IAM Assumed Role 的方式获取 S3 访问凭证 (3.1.2+ 支持)
CREATE CATALOG `glue_hive_iamrole` PROPERTIES (
'type' = 'hms',
'hive.metastore.type' = 'glue',
'glue.region' = 'us-east-1',
'glue.endpoint' = 'https://glue.us-east-1.amazonaws.com',
'glue.role_arn' = '<role_arn>'
);
2.1 & 3.0 版本
- S3
非 EC2 环境下,需要使用 aws configure 配置 Credentials 信息,同时在~/.aws 目录下生成 credentials 文件。
或者显示的在创建 catalog 参数中新增凭据提供方式 "aws.catalog.credentials.provider.factory.class"="com.amazonaws.glue.catalog.credentials.ConfigurationAWSCredentialsProviderFactory"
create catalog hive_glue PROPERTIES(
'type' = 'hms',
'hive.metastore.type' = 'glue',
'glue.endpoint' = 'https://glue.ap-northeast-1.amazonaws.com',
'glue.region' = 'ap-northeast-1',
'glue.access_key' = '<ak>',
'glue.secret_key' = '<sk>'
);
Aliyun DLF
3.1+ 版本
- DLF 1.0
CREATE CATALOG hive_dlf_oss_test_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.type' = 'dlf',
'dlf.uid' = '203225413946383283',
'dlf.catalog_id' = 'p2_regression_case',
'dlf.endpoint' = 'dlf.cn-beijing.aliyuncs.com',
'dlf.region' = 'cn-beijing',
'dlf.access_key' = '<ak>',
'dlf.secret_key' = '<sk>'
);
2.1 & 3.0 版本
- DLF 1.0
CREATE CATALOG hive_dlf_oss_test_catalog PROPERTIES (
'type' = 'hms',
'hive.metastore.type' = 'dlf',
'dlf.uid' = '203225413946383283',
'dlf.catalog.id' = 'p2_regression_case',
'dlf.endpoint' = 'dlf.cn-beijing.aliyuncs.com',
'dlf.region' = 'cn-beijing',
'dlf.access_key' = '<ak>',
'dlf.secret_key' = '<sk>'
);
查询操作
基础查询
配置好 Catalog 后,可以通过以下方式查询 Catalog 中的表数据:
-- 1. switch to catalog, use database and query
SWITCH hive_ctl;
USE hive_db;
SELECT * FROM hive_tbl LIMIT 10;
-- 2. use hive database directly
USE hive_ctl.hive_db;
SELECT * FROM hive_tbl LIMIT 10;
-- 3. use full qualified name to query
SELECT * FROM hive_ctl.hive_db.hive_tbl LIMIT 10;
查询 Hive 分区
可以通过下面两种方式查询 Hive 分区信息。
-
SHOW PARTITIONS FROM [catalog.][db.]hive_table该语句可以列出指定 Hive 表的所有分区以及分区值信息。
SHOW PARTITIONS FROM hive_table;
+--------------------------------+
| Partition |
+--------------------------------+
| pt1=2024-10-10/pt2=beijing |
| pt1=2024-10-10/pt2=shanghai |
| pt1=2024-10-11/pt2=beijing |
| pt1=2024-10-11/pt2=shanghai |
| pt1=2024-10-12/pt2=nanjing |
+--------------------------------+ -
使用
table$partitions元数据表自 2.1.7 和 3.0.3 版本开始,用户可以通过
table$partitions元数据表查询 Hive 分区信息。table$partitions本质上是一个关系表,每个分区列为一列,所以可以使用在任意 SELECT 语句中。SELECT * FROM hive_table$partitions;
+------------+-------------+
| pt1 | pt2 |
+------------+-------------+
| 2024-10-10 | beijing |
| 2024-10-10 | shanghai |
| 2024-10-12 | nanjing |
| 2024-10-11 | beijing |
| 2024-10-11 | shanghai |
+------------+-------------+
自 4.1.4 版本起,Hive 目录式分区中的默认分区标记 __HIVE_DEFAULT_PARTITION__ 会被解析为真正的 NULL 值,而不再编码为字符串 \N。同时,分区路径中真实存储的字符串 \N 会被原样保留为数据。
4.1.4 之前这两种情况无法区分,查询结果中都会显示为 \N。升级后,WHERE <partition_col> IS NULL 才能正确匹配 Hive 默认分区。
查询 Hive 事务表
Hive Transactional 表是 Hive 中支持 ACID 语义的表。详情可见 Hive Transactions。
-
Hive Transactional 表支持情况
表类型 在 Hive 中支持的操作 Hive 表属性 支持的 Hive 版本 Full-ACID Transactional Table 支持 Insert, Update, Delete 操作 'transactional'='true'4.x,3.x,2.x,其中 2.x 需要在 Hive 中执行完 Major Compaction 才可以读取。 Insert-Only Transactional Table 只支持 Insert 操作 'transactional'='true','transactional_properties'='insert_only'4.x,3.x,2.x 在创建 catalog 的时候需要指定 hive.version。 -
当前限制
目前不支持 Original Files 的场景。当一个表转换成 Transactional 表之后,后续新写的数据文件会使用 Hive Transactional 表的 Schema,但是已经存在的数据文件是不会转化成 Transactional 表的 Schema,这样的文件称为 Original Files。
查询 Hive View
支持查询 Hive View。但注意有以下限制:
-
Hive View 的定义语句(HiveQL)必须是 Doris 支持的 SQL 语句。否则会出现解析错误。
-
部分 HiveQL 支持的函数可能和 Doris 支持的函数同名,但行为不一致,这可能导致最终结果和使用 Hive 查询的结果不一致。如果用户遇到此类问题,可以向社区反馈。
相关参数
-
Session 变量
参数名称 描述 默认值 版本 hive_parquet_use_column_namestrueDoris 在读取 Hive 表 Parquet 数据类型时,默认会根据 Hive 表的列名从 Parquet 文件中找同名的列来读取数据。当该变量为 false时,Doris 会根据 Hive 表中的列顺序从 Parquet 文件中读取数据,与列名无关。类似于 Hive 中的parquet.column.index.access变量。该参数只适用于顶层列名,对 Struct 内部无效。2.1.6+, 3.0.3+ hive_orc_use_column_namestrue与 hive_parquet_use_column_names类似,针对的是 Hive 表 ORC 数据类型。类似于 Hive 中的orc.force.positional.evolution变量。2.1.6+, 3.0.3+
写入操作
可以通过 INSERT 语句将数据写入到 Hive 表中。支持写入到由 Doris 创建的 Hive 表,或者 Hive 中已存在的且格式支持的表。
对于分区表,会根据数据写入对应分区,或者创建新分区。自 4.1.5 版本起,也支持通过 PARTITION (列名 = 字面量) 指定静态分区,或者混合使用静态和动态分区列。静态分区列不要重复放入 INSERT 的目标列列表或 SELECT / VALUES 输出中;剩余动态分区列仍由输入数据提供。
INSERT INTO
INSERT 操作会将数据以追加的方式写入到目标表中。
INSERT INTO hive_tbl VALUES (val1, val2, val3, val4);
INSERT INTO hive_ctl.hive_db.hive_tbl SELECT col1, col2 FROM internal.db1.tbl1;
INSERT INTO hive_tbl(col1, col2) VALUES (val1, val2);
INSERT INTO hive_tbl(col1, col2, partition_col1, partition_col2) VALUES (1, 2, "beijing", "2023-12-12");
自 4.1.5 版本起,支持写入数据到静态分区,或者静态分区和动态分区混合使用:
-- Full Static Partition
INSERT INTO hive_tbl PARTITION (partition_col1='2026-07-30', partition_col2='beijing')
VALUES (val1, val2);
INSERT INTO hive_tbl PARTITION (partition_col1='2026-07-30', partition_col2='beijing')
SELECT col1, col2 FROM source_table;
-- Hybrid Partition Mode: "partition_col1" is static, "partition_col2" comes from SELECT dynamically
INSERT INTO hive_tbl PARTITION (partition_col1='2026-07-30')
VALUES (val1, val2, partition_val2);
INSERT INTO hive_tbl PARTITION (partition_col1='2026-07-30')
SELECT col1, col2, partition_col2 FROM source_table;
INSERT OVERWRITE
INSERT OVERWRITE 会使用新的数据完全覆盖原有表中的数据。
INSERT OVERWRITE TABLE hive_tbl VALUES(val1, val2, val3, val4);
INSERT OVERWRITE TABLE hive_ctl.hive_db.hive_tbl(col1, col2) SELECT col1, col2 FROM internal.db1.tbl1;
自 4.1.5 版本起,支持覆盖静态分区,或者静态分区和动态分区混合使用:
-- Full Static Partition
INSERT OVERWRITE TABLE hive_tbl PARTITION (partition_col1='2026-07-30', partition_col2='beijing')
VALUES (val1, val2);
INSERT OVERWRITE TABLE hive_tbl PARTITION (partition_col1='2026-07-30', partition_col2='beijing')
SELECT col1, col2 FROM source_table;
-- Hybrid Partition Mode: "partition_col1" is static, "partition_col2" comes from SELECT dynamically
INSERT OVERWRITE TABLE hive_tbl PARTITION (partition_col1='2026-07-30')
VALUES (val1, val2, partition_val2);
INSERT OVERWRITE TABLE hive_tbl PARTITION (partition_col1='2026-07-30')
SELECT col1, col2, partition_col2 FROM source_table;
INSERT OVERWRITE 的语义与 Hive 一致,有如下行为:
-
当目的表是分区表,而源表为空表时,操作不会产生任何影响。目的表数据无变化。
-
当目的表是非分区表,而源表是空表是,目的表会被清空。
-
自 4.1.5 版本起,支持指定静态分区以及静态和动态分区混合写入。但是即便指定了静态分区,如果查询内容为空,则指定的分区也不会被清理。
静态分区完整示例(4.1.5 起)
先配置本页所述的 Hive Catalog,并准备已有的 hive_ctl.hive_db 数据库,以及建表、写入和查询权限;用于写入的 Catalog 需已设置 fs.defaultFS。下面混合使用静态日期和动态地区,再仅覆盖其中一个完整静态分区:
CREATE TABLE hive_ctl.hive_db.static_write_demo (
id INT,
dt STRING,
region STRING
)
ENGINE=HIVE
PARTITION BY LIST (dt, region) ()
PROPERTIES ("file_format" = "parquet");
INSERT INTO hive_ctl.hive_db.static_write_demo PARTITION (dt='2026-10-01')
VALUES (1, 'beijing'), (2, 'shanghai');
INSERT OVERWRITE TABLE hive_ctl.hive_db.static_write_demo
PARTITION (dt='2026-10-01', region='beijing') VALUES (3);
SELECT id, dt, region FROM hive_ctl.hive_db.static_write_demo ORDER BY id;
+----+------------+----------+
| id | dt | region |
+----+------------+----------+
| 2 | 2026-10-01 | shanghai |
| 3 | 2026-10-01 | beijing |
+----+------------+----------+
静态分区值必须是字面量;不能重复指定同一分区键,也不能将静态分区列重复放入 INSERT 的显式列列表。静态键名按不区分大小写匹配,不存在的分区列会报错。
CTAS
可以通过 CTAS(CREATE TABLE AS SELECT) 语句创建 Hive 表并写入数据:
CREATE TABLE hive_ctas ENGINE=hive AS SELECT * FROM other_table;
CTAS 支持指定文件格式、分区方式等信息,如:
CREATE TABLE hive_ctas ENGINE=hive
PARTITION BY LIST (pt1, pt2) ()
AS SELECT col1,pt1,pt2 FROM part_ctas_src WHERE col1>0;
CREATE TABLE hive_ctl.hive_db.hive_ctas (col1,col2,pt1) ENGINE=hive
PARTITION BY LIST (pt1) ()
PROPERTIES (
"file_format"="parquet",
"compression"="zstd"
)
AS SELECT col1,pt1 as col2,pt2 as pt1 FROM test_ctas.part_ctas_src WHERE col1>0;
相关参数
-
BE 配置
参数名称 描述 默认值 hive_sink_max_file_size最大的数据文件大小。当写入数据量超过该大小后会关闭当前文件,滚动产生一个新文件继续写入。 1GB table_sink_partition_write_max_partition_nums_per_writerBE 节点上每个 Instance 最大写入的分区数目。 128 table_sink_non_partition_write_scaling_data_processed_threshold非分区表开始 scaling-write 的数据量阈值。每增加 table_sink_non_partition_write_scaling_data_processed_threshold数据就会发送给一个新的 writer(instance) 进行写入。scaling-write 机制主要是为了根据数据量来使用不同数目的 writer(instance) 来进行写入,会随着数据量的增加而增大写入的 writer(instance) 数目,从而提高并发写入的吞吐。当数据量比较少的时候也会节省资源,并且尽可能地减少产生的文件数目。25MB table_sink_partition_write_min_data_processed_rebalance_threshold分区表开始触发重平衡的最少数据量阈值。如果 当前累积的数据量-自从上次触发重平衡或者最开始累积的数据量>=table_sink_partition_write_min_data_processed_rebalance_threshold,就开始触发重平衡机制。如果发现最终生成的文件大小差异过大,可以调小改阈值来增加均衡度。当然过小的阈值会导致重平衡的成本增加,可能会影响性能。25MB table_sink_partition_write_min_partition_data_processed_rebalance_threshold分区表开始进行重平衡时的最少的分区数据量阈值。如果 当前分区的数据量>=阈值*当前分区已经分配的 task 数目,就开始对该分区进行重平衡。如果发现最终生成的文件大小差异过大,可以调小改阈值来增加均衡度。当然过小的阈值会导致重平衡的成本增加,可能会影响性能。15MB
库表管理
用户可以通过 Doris 在 Hive Metastore 中创建、删除库表。注意,Doris 只是调用 Hive Metastore 的 API 进行相应操作,Doris 本身的元数据并不存储和持久化任何 Hive 的元数据。
创建和删除库
可以通过 SWITCH 语句切换到对应的 Catalog 下,执行 CREATE DATABASE 语句:
SWITCH hive_ctl;
CREATE DATABASE [IF NOT EXISTS] hive_db;
也可以使用全限定名创建,或指定 location,如:
CREATE DATABASE [IF NOT EXISTS] hive_ctl.hive_db;
CREATE DATABASE [IF NOT EXISTS] hive_ctl.hive_db
PROPERTIES ('location'='hdfs://172.21.16.47:4007/path/to/db/');
之后可以通过 SHOW CREATE DATABASE 命令可以查看 Database 的 Location 信息:
mysql> SHOW CREATE DATABASE hive_db;
+----------+---------------------------------------------------------------------------------------------+
| Database | Create Database |
+----------+---------------------------------------------------------------------------------------------+
| hive_db | CREATE DATABASE hive_db LOCATION 'hdfs://172.21.16.47:4007/usr/hive/warehouse/hive_db.db' |
+----------+---------------------------------------------------------------------------------------------+
删除
DROP DATABASE [IF EXISTS] hive_ctl.hive_db;
对于 Hive Database,必须先删除这个 Database 下的所有表后,才能删除 Database,否则会报错。这个操作会同步删除 Hive 中对应的 Database。
创建和删除表
-
创建
Doris 支持在 Hive 中创建分区或非分区表。
-- Create unpartitioned hive table
CREATE TABLE unpartitioned_table (
`col1` BOOLEAN COMMENT 'col1',
`col2` INT COMMENT 'col2',
`col3` BIGINT COMMENT 'col3',
`col4` CHAR(10) COMMENT 'col4',
`col5` FLOAT COMMENT 'col5',
`col6` DOUBLE COMMENT 'col6',
`col7` DECIMAL(9,4) COMMENT 'col7',
`col8` VARCHAR(11) COMMENT 'col8',
`col9` STRING COMMENT 'col9'
) ENGINE=hive
PROPERTIES (
'file_format'='parquet'
);
-- Create partitioned hive table
-- The partition columns must be in table's column definition list
CREATE TABLE partition_table (
`col1` BOOLEAN COMMENT 'col1',
`col2` INT COMMENT 'col2',
`col3` BIGINT COMMENT 'col3',
`col4` DECIMAL(2,1) COMMENT 'col4',
`pt1` VARCHAR COMMENT 'pt1',
`pt2` VARCHAR COMMENT 'pt2'
) ENGINE=hive
PARTITION BY LIST (pt1, pt2) ()
PROPERTIES (
'file_format'='orc',
'compression'='zlib'
);
-- Create text format table(Since 2.1.7 & 3.0.3)
CREATE TABLE text_table (
`id` INT,
`name` STRING
) PROPERTIES (
'file_format'='text',
'compression'='gzip',
'field.delim'='\t',
'line.delim'='\n',
'collection.delim'=';',
'mapkey.delim'=':',
'serialization.null.format'='\\N',
'escape.delim'='\\'
);创建后,可以通过
SHOW CREATE TABLE命令查看 Hive 的建表语句。注意,不同于 Hive 中的建表语句。在 Doris 中创建 Hive 分区表时,分区列也必须写到 Table 的 Schema 中。同时,分区列必须在所有 Schema 的最后,且顺序保持一致。
提示对于某些默认开启 ACID 事务特性的 Hive 集群,使用 Doris 建表后,表属性
transactional会为true。而 Doris 只支持部分 Hive 事务表的特性,因此可能会导致 Doris 创建的 Hive,Doris 本身无法读取的问题。因此,需要在建表的属性中,显式增加:"transactional" = "false",来创建非事务的 Hive 表:CREATE TABLE non_acid_table(
`col1` BOOLEAN COMMENT 'col1',
`col2` INT COMMENT 'col2',
`col3` BIGINT COMMENT 'col3'
) ENGINE=hive
PROPERTIES (
'transactional'='false',
); -
删除
可以通过
DROP TABLE语句删除一个 Hive 表。当前删除表后,会同时删除数据,包括分区数据。 -
列类型映射
参考【列类型映射】部分。需要额外注意一下限制:
- 列类型只能为默认的 Nullable,不支持
NOT NULL。 - Hive 3.0 支持设置默认值。如果需要设置默认值,则需要在 Catalog 属性中显示的添加
"hive.version" = "3.0.0"。 - 插入数据后,如果类型不能够兼容,例如
'abc'插入到数值类型,则会转为null值插入。
- 列类型只能为默认的 Nullable,不支持
-
分区
Hive 中的分区类型对应 Doris 中的 List 分区。因此,在 Doris 中 创建 Hive 分区表,需使用 List 分区的建表语句,但无需显式的枚举各个分区。在写入数据时,Doris 会根据数据的值,自动创建对应的 Hive 分区。支持创建单列或多列分区表。
-
文件格式
-
ORC(默认)
-
Parquet
注意,DATETIME 类型写入到 Parquet 文件时,物理类型使用的是 INT96 而非 INT64。目的是兼容 Hive 4.0 版本之前的逻辑。
-
Text(自 2.1.7 和 3.0.3 版本开始支持)
-
Text 格式还支持以下表属性:
-
field.delim:列分隔符。默认\1。 -
line.delim:行分隔符。默认\n。 -
collection.delim:复杂类型中各元素之间的分隔符。默认\2。 -
mapkey.delim:Map 类型的键值分割符。默认\3 -
serialization.null.format:NULL 值的存储格式。默认\N。 -
escape.delim:转移字符。默认\。
-
-
-
压缩格式
-
Parquet:snappy(默认)、zstd、plain。(Plain 就是不采用压缩)
-
ORC:snappy、zlib(默认)、zstd、plain。(Plain 就是不采用压缩)
-
Text:gzip、defalte、bzip2、zstd、lz4、lzo、snappy、plain(默认)。(Plain 就是不采用压缩)
-
-
存储介质
-
HDFS
-
对象存储
-
订阅 Hive Metastore 事件
通过让 FE 节点定时读取 HMS 的 Notification Event 来感知 Hive 表元数据的实时变更情况,以提高元数据的时效性。目前支持处理如下 Event:
| 事件 | 事件行为和对应的动作 |
|---|---|
| CREATE DATABASE | 在对应数据目录下创建数据库。 |
| DROP DATABASE | 在对应数据目录下删除数据库。 |
| ALTER DATABASE | 此事件的影响主要有更改数据库的属性信息,注释及默认存储位置等,这些改变不影响 Doris 对外部数据目录的查询操作,因此目前会忽略此 Event。 |
| CREATE TABLE | 在对应数据库下创建表。 |
| DROP TABLE | 在对应数据库下删除表,并失效表的缓存。 |
| ALTER TABLE | 如果是重命名,先删除旧名字的表,再用新名字创建表,否则失效该表的缓存。 |
| ADD PARTITION | 在对应表缓存的分区列表里添加分区。 |
| DROP PARTITION | 在对应表缓存的分区列表里删除分区,并失效该分区的缓存。 |
| ALTER PARTITION | 如果是重命名,先删除旧名字的分区,再用新名字创建分区,否则失效该分区的缓存。 |
-
当导入数据导致文件变更,分区表会触发
ALTER PARTITION时间,非分区表会触发ALTER TABLE事件。 -
如果绕过 HMS 直接操作文件系统的话,HMS 不会生成对应事件,因此 Doris 也无法感知元数据变化。
该特性在 fe.conf 中有如下相关参数:
-
enable_hms_events_incremental_sync: 是否开启元数据自动增量同步功能,默认关闭。 -
hms_events_polling_interval_ms: 读取 event 的间隔时间,默认值为 10000,单位:毫秒。 -
hms_events_batch_size_per_rpc: 每次读取 event 的最大数量,默认值为 500。
如果想使用该特性 (华为云 MRS 除外),需要更改 HMS 的 hive-site.xml 并重启 HMS 和 HiveServer2:
<property>
<name>hive.metastore.event.db.notification.api.auth</name>
<value>false</value>
</property>
<property>
<name>hive.metastore.dml.events</name>
<value>true</value>
</property>
<property>
<name>hive.metastore.transactional.event.listeners</name>
<value>org.apache.hive.hcatalog.listener.DbNotificationListener</value>
</property>
华为云 MRS 需要更改 hivemetastore-site.xml 并重启 HMS 和 HiveServer2:
<property>
<name>metastore.transactional.event.listeners</name>
<value>org.apache.hive.hcatalog.listener.DbNotificationListener</value>
</property>
附录
事务机制
对 Hive 的写入操作会被放在一个单独的事务里,在事务提交前,数据对外不可见。只有当提交该事务后,表的相关操作才对其他人可见。
事务能保证操作的原子性,事务内的所有操作,要么全部成功,要么全部失败。
事务不能完全保证操作的隔离性,只能尽力而为,通过分离文件系统操作和 对 Hive Metastore 的元数据操作来尽量减少不一致的时间窗口。
比如在一个事务中,需要修改 Hive 表的多个分区。假设这个任务分成两批进行操作,在第一批操作已经完成、第二批操作还未完成时,第一批分区已经对外可见,外部可以读取到第一批分区,但读不到第二批分区。
在事务提交过程中出现任何异常,都会直接回退该事务,包括对 HDFS 文件的修改、以及对 Hive Metastore 元数据的修改,不需要用户做其他处理。
并发写入机制
当前 Apache Doris 支持使用多个插入语句进行并发写入。不过需要注意的是,用户需要控制并发写入不产生可能冲突的情况。
因为普通非事务 Hive 表缺少完备的事务机制。通过上文介绍的 Apache Doris 事务机制我们知道目前 Apache Doris 中的实现只能是尽力而为地减少可能不一致的时间窗口,而无法保证真正的 ACID。因此在 Apache Doris 中进行并发写入 Hive 表可能会导致数据一致性问题。
-
INSERT并发操作 -
INSERT为数据追加操作,在并发执行INSERT时,不会产生冲突,操作会产生预期的结果。 -
INSERT OVERWRITE并发操作 -
如果使用
INSERT OVERWRITE对同一表或分区并发写入,可能会导致数据丢失或损坏,结果可能是不确定的。 -
一般有以下几种解决方案:
-
对于分区表,可以将数据写入不同的分区,并发操作不同分区不会产生冲突。
-
对于非分区表,可以同时执行 INSERT,而不使用 INSERT OVERWRITE,这样不会产生冲突的问题。
-
对于可能产生冲突的操作,需要用户在业务侧控制同一时间只有一个写入在进行。
-
HDFS 文件操作
在 HDFS 上的 Hive 表数据通常会先写入到临时目录,然后通过 rename 等文件系统操作进行最终的文件提交。这里我们详细介绍不同数据操作中,HDFS 上文件的具体操作。
数据的临时目录格式为:/tmp/.doris_staging/<username>/<uuid>
写入的数据文件名称格式为:<query-id>_<uuid>-<index>.<compress-type>.<file-type>
下面举例说明各种情况下的文件操作。
-
非分区表
-
Append(追加写入)
-
目标表目录:
hdfs://ns/usr/hive/warehouse/example.db/table1 -
临时文件:
hdfs://ns/tmp/.doris_staging/root/f02247cb662846038baae272af5eeb05/b35fdbcea3a4e39-86d1f36987ef1492_7e3985bf-9de9-4fc7-b84e-adf11aa08756-0.orc -
提交阶段会把所有临时文件移动到目标表目录下。
-
-
Overwrite(覆盖写)
-
目标表目录:
hdfs://ns/usr/hive/warehouse/example.db/table1 -
临时文件:
hdfs://ns/tmp/.doris_staging/root/f02247cb662846038baae272af5eeb05/b35fdbcea3a4e39-86d1f36987ef1492_7e3985bf-9de9-4fc7-b84e-adf11aa08756-0.orc -
提交阶段:
-
目标表目录重命名为目标表临时目录:
hdfs://ns/usr/hive/warehouse/example.db/_temp_b35fdbcea3a4e39-86d1f36987ef1492_table1 -
临时目录重命名为目标表目录。
-
删除目标表临时目录。
-
-
-
分区表
-
Add(添加到新分区)
-
目标表目录:
hdfs://ns/usr/hive/warehouse/example.db/table2/part_col=2024-01-01 -
临时文件:
hdfs://ns/tmp/.doris_staging/root/a7eac7505d7a42fdb06cb9ef1ea3e912/par1=a/d678a74d232345e0-b659e2fb58e86ffd_549ad677-ee75-4fa1-b8a6-3e821e1dae61-0.orc -
提交阶段,会将临时目录重命名为目标表目录
-
-
Append(写入数据到已存在的分区)
-
目标表目录:
hdfs://ns/usr/hive/warehouse/example.db/table2/part_col=2024-01-01 -
临时文件:
hdfs://ns/tmp/.doris_staging/root/a7eac7505d7a42fdb06cb9ef1ea3e912/par1=a/d678a74d232345e0-b659e2fb58e86ffd_549ad677-ee75-4fa1-b8a6-3e821e1dae61-0.orc -
提交阶段,会将临时目录下的文件,移动到目标表目录下。
-
-
Overwrite(覆盖已有分区)
-
目标表目录:
hdfs://ns/usr/hive/warehouse/example.db/table2/part_col=2024-01-01 -
临时文件:
hdfs://ns/tmp/.doris_staging/root/a7eac7505d7a42fdb06cb9ef1ea3e912/par1=a/d678a74d232345e0-b659e2fb58e86ffd_549ad677-ee75-4fa1-b8a6-3e821e1dae61-0.orc -
提交阶段:
-
目标表分区目录重命名为目标表临时分区目录:
hdfs://ns/usr/hive/warehouse/example.db/table2/_temp_d678a74d232345e0-b659e2fb58e86ffd_part_col=2024-01-01 -
临时分区目录重命名为目标表分区目录。
-
删除目标表临时分区目。
-
-
版本更新记录
| Doris 版本 | 功能支持 |
|---|---|
| 2.1.6 | 支持 Hive 表数据写回 |
| 3.0.4 | 支持 JsonSerDe 格式的 Hive 表。支持 Hive4 的事务表。 |