性能调优的最佳实践
查看与配置集群、存储数据和编写查询相关的某些性能调优指南,以便您可以保护集群和相关服务、自动扩展资源以处理查询等。
最佳实践
- 使用 Ranger 安全服务来保护您的集群和依赖服务。
- 使用 ORC 文件格式存储数据。其他的,例如 Parquet 也受支持,但对于 Hive 查询没有那么快。
- 通过检查解释计划确保查询完全矢量化。
原文链接:https://docs.cloudera.com/cdp-private-cloud-base/latest/hive-performance-tuning/topics/hive_prepare_to_tune_performance.html
ORC 文件格式
您可以通过多种方式节省存储空间,但使用优化行列式 (ORC) 文件格式来存储 Apache Hive 数据最为有效。ORC 是 Hive 数据的默认存储。
出于以下原因,推荐用于 Hive 数据存储的 ORC 文件格式:
- 高效压缩:存储为列并进行压缩,从而减少磁盘读取。列格式也是 Tez 中矢量化优化的理想选择。
- 快速读取:ORC 具有内置索引、最小值/最大值和其他聚合,这些聚合会导致在读取过程中跳过整个条带。此外,谓词下推将过滤器推送到读取中,以便读取最少的行。布隆过滤器进一步减少了返回的行数。
在大规模部署中得到验证:Facebook 使用 ORC 文件格式进行 300 PB 部署。
ORC 总体上提供了最佳的 Hive 性能。另外,要指定存储格式,还可以为表指定压缩算法,如下例所示:
代码语言:javascript复制CREATE TABLE addresses (
name string,
street string,
city string,
state string,
zip int
) STORED AS orc TBLPROPERTIES ("orc.compress"="Zlib");
通常不需要设置压缩算法,因为您的 Hive 设置包括默认算法。使用 ORC 高级属性,您可以为点查找中经常使用的列创建布隆过滤器。
Hive 支持 Parquet 和其他格式用于仅插入的 ACID 表和外部表。您还可以编写自己的 SerDes(Serializers、Deserializers)接口来支持自定义文件格式。
高级 ORC 属性
通常,您不需要修改优化行列式 (ORC) 属性,但偶尔,Cloudera 支持建议进行此类更改。查看可以配置 ORC 以满足您的需要的属性键、默认值和描述。
属性键和默认值
您可以使用 Cloudera Manager 中的安全阀功能来更改 ORC 属性。
键值 | 默认设置 | 描述 |
---|---|---|
orc.compress | ZLIB | 压缩类型(NONE、ZLIB、SNAPPY)。 |
orc.compress.size | 262,144 | 每个压缩块中的字节数。 |
orc.stripe.size | 268,435,456 | 每个条带中的字节数。 |
orc.row.index.stride | 10,000 | 索引条目之间的行数 (>= 1,000)。 |
orc.create.index | true | 设置是否创建行索引。 |
orc.bloom.filter.columns | -- | 必须为其创建布隆过滤器的以逗号分隔的列名称列表。 |
orc.bloom.filter.fpp | 0.05 | 布隆过滤器的误报概率。必须大于 0.0 且小于 1.0。 |
原文链接:https://docs.cloudera.com/cdp-private-cloud-base/latest/hive-performance-tuning/topics/hive_maximize_storage_resources_using_orc.html
使用分区提高性能
您必须了解什么是分区修剪、如何启用动态分区以及批量加载数据所需的配置,以确保显着提高性能。您可以使用分区来显着提高性能。您可以设计 Hive 表和物化视图分区以映射到文件系统/对象存储上的物理目录。例如,按日期-时间分区的表可以组织每天加载到 Hive 中的数据。
大型部署可以有数以万计的分区。当 Hive 在查询处理期间发现分区键时,会间接进行分区修剪。例如,加入维度表后,分区键可能来自维度表。查询按分区过滤列,限制对一个或几个匹配分区进行的扫描。当 WHERE 子句中存在分区键时,会直接进行分区修剪。分区列是虚拟的,不会写入主表,因为这些列对于整个分区是相同的。
您不需要指定动态分区列。如果启用动态分区,Hive 会生成分区规范。
加载1到9个分区的配置:
代码语言:javascript复制SET hive.exec.dynamic.partition.mode=nonstrict;
SET hive.exec.dynamic.partition=true;
要将数据批量加载到分区 ORC 表中,您可以使用以下属性,优化数据加载到 10 个或更多分区的性能。
加载 10 个或更多分区的配置:
代码语言:javascript复制hive.optimize.sort.dynamic.partition=true
原文链接:https://docs.cloudera.com/cdp-private-cloud-base/latest/hive-performance-tuning/topics/hive_improving_performance_using_partitions.html
Hive 中的分桶表
如果您将数据从较早的 Apache Hive 版本迁移到 Hive 3,您可能需要处理影响性能的分桶表。查看 CDP 如何简化处理存储桶。您将了解处理动态功能的最佳实践。
您可以将表或分区划分为桶,桶的存储方式如下:
- 作为表目录中的文件。
- 如果表已分区,则作为分区目录。
没有必要在 Hive 3 表中指定桶。在 CDP 中,Hive 3 隐式存储数据,并且不像早期版本(ACID V1)那样需要用户密钥或用户提供的存储桶编号。例如:
V1:
代码语言:javascript复制CREATE TABLE hello_acid (load_date date, key int, value int)
CLUSTERED BY(key) INTO 3 BUCKETS
STORED AS ORC TBLPROPERTIES ('transactional'='true');
V2:
代码语言:javascript复制CREATE TABLE hello_acid_v2 (load_date date, key int, value int);
ACID V2 表的性能与使用桶的非 ACID 表相当。ACID V2 表与原生云存储兼容。
在从早期版本迁移的表中使用存储桶的一个常见挑战是在工作负载或数据向上或向下扩展时保持查询性能。例如,您可能拥有一个使用 16 个存储桶以支持 1000 个用户的平稳运行的环境,但是如果您不及时调整存储桶和分区,用户数量在一两天内激增至 100,000 会产生问题。由于在您构建了一个包含存储桶的表之后,必须重新加载包含存储桶数据的整个表以减少、添加或删除存储桶,因此调整存储桶很复杂。
在使用 Tez 的 CDP 中,您只需要处理最大表的桶。如果工作负载需求快速变化,较小表的桶会动态变化以完成表 JOIN。
您执行以下与存储桶相关的任务:
- 设置hive-site.xml以启用存储桶
SET hive.tez.bucket.pruning=true
- 分区和分桶的批量加载表:
将数据加载到分区和分桶的表中时,请设置以下属性以优化过程:
代码语言:javascript复制SET hive.optimize.sort.dynamic.partition=true
如果您在 user_id 数据上有 20 个存储桶,则以下查询仅返回与 user_id = 1 关联的数据:SELECT * FROM tab WHERE user_id = 1;
为了最好地利用 Tez 上表桶的动态能力,请采用以下做法:
- 对最大表的桶使用单个键。
- 通常,您需要按最大维度表对主表进行分桶。例如,销售表可能按客户分类,而不是按商品或商店分类。但是,在这种情况下,销售表按商品和商店排序。
- 通常,不要对同一列进行分桶和排序。
存储区文件多于行数的表表明您应该重新考虑表的存储区划分方式。
原文链接:https://docs.cloudera.com/cdp-private-cloud-base/latest/hive-performance-tuning/topics/hive_bucketed_tables.html