向 where 子句添加冗余 true 条件如何提高 Hive 查询性能?



让我用一个例子来演示。我们有一个包含 100 万条记录的表,其中包含几列。请注意 where 子句中的 dt 条件。

create table tbl as
select * from some_table
where dt > '20200601'
limit 1000000;

现在,如果我使用 Hiveexplain命令获取示例查询的执行计划,我会得到以下结果:

explain
select id from tbl
where 
id > 1000; 
Stage-0
Fetch Operator
limit:-1
Stage-1
Map 1
File Output Operator [FS_3]
Select Operator [SEL_2] (rows=333333 width=196)
Output:["_col0"]
Filter Operator [FIL_4] (rows=333333 width=196)
predicate:(rid > 1000L)
TableScan [TS_0] (rows=1000000 width=196)
user@tbl,tbl, ACID table,Tbl:COMPLETE,Col:NONE,Output:["id"]

优化程序报告返回 333k 条记录以供选择。如果我在另一列上添加另一个Where条件(我知道无论如何都是正确的(,优化器为 SELECT 查询报告的数字要小得多。

explain
select id from tbl
where 
id > 1000; 
AND dt > '20200601';
Stage-0
Fetch Operator
limit:-1
Stage-1
Map 1
File Output Operator [FS_3]
Select Operator [SEL_2] (rows=111111 width=196)
Output:["_col0"]
Filter Operator [FIL_4] (rows=111111 width=196)
predicate:((id > 1000L) and (dt > '20200601'))
TableScan [TS_0] (rows=1000000 width=196)
user@tbl,tbl, ACID table,Tbl:COMPLETE,Col:NONE,Output:["id","dt"]

对于我在工作中使用的日常查询,我测试了这种情况,并且经常(并非总是(向Where子句添加另一个条件,以减少执行计划中 Select 运算符的数量。 我处理的是几十亿条记录的表,任何查询的优化对我来说都是个好消息。

我应该如何解释"解释"命令中选定运算符编号的减少?

  • 这是否意味着添加一个虚拟条件(显示 使用解释命令减少(可能会改善查询 性能?
  • 除了可读性和风格,还有没有 在 Where 子句中添加此类虚拟条件的缺点,可以吗 实际上损害了查询性能?

谢谢

计划中的数字取自统计数据,可以过时或根本不存在。如果没有统计信息,则估计行数,并且此估计不准确。Hive 只是估计所有 WHERE 条件都是选择性的。

尝试收集列的统计信息并再次检查计划,数字可能会更改。 还要确保在执行 EXPLAIN 之前打开统计信息用法:

set hive.cbo.enable=true;
set hive.compute.query.using.stats=true;
set hive.stats.fetch.column.stats=true;    --this can be expensive
set hive.stats.fetch.partition.stats=true; --this can be expensive

无论如何,计划中的数字是基于统计数据和文件大小的估计,估计的平均记录大小,而不是实际计数,因此它们很少是100%准确的。在这种情况下,可以压缩文件并估计压缩率。

在简单查询中,估计的行数不会影响查询 DAG 和性能。

统计信息可能会影响复杂查询的 DAG,例如,如果 Hive 错误地估计了行数,并且将为不适合内存的表运行映射联接,则会导致 OOM,或者将生成次优计划。

在您的情况下,虚拟条件并没有真正提高性能,只需检查两个查询的执行时间,您就会看到。

最新更新