让我举个例子来说明。我们有一个表,有一百万条记录,有几列。注意where子句中的dt条件。
create table tbl as
select * from some_table
where dt > '20200601'
limit 1000000;
现在,如果我用Hive explain
命令获取示例查询的执行计划,我得到以下结果:
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"]
优化器报告为select返回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操作符的数量。我处理的表有几十亿条记录,任何查询优化对我来说都是好消息。
如何解释explain命令中select运算符数的减少?
这是否意味着添加一个dummy where条件(用explain命令显示缩减)可以潜在地提高查询性能?
除了可读性和样式之外,在where子句中添加这样的伪条件还有什么坏处吗?它真的会影响查询性能吗?
谢谢
1条答案
按热度按时间ddrv8njm1#
计划中的数字是从统计数字中提取出来的,这些数字可能是陈旧的,也可能根本不存在。如果缺少统计信息,则估计行数,并且此估计不准确。Hive只是估计所有的条件都是有选择性的。
尝试收集列的统计数据并再次检查计划,数字可能会改变。在执行explain之前,还要确保statistics usage已打开:
无论如何,计划中的这些数字是基于统计数据和文件大小的估计,估计的平均记录大小,而不是实际计数,因此它们很少100%准确。在这种情况下,可以压缩文件并估计压缩比。
在简单查询中,估计的行数不会影响查询dag和性能。
对于复杂的查询,统计信息可能会影响dag,例如,如果配置单元错误地估计了行数,并且将对内存中不适合的表运行map join,那么它将导致oom,或者将生成次优计划。
在您的案例中,虚拟条件并不能真正提高性能,只要检查两个查询的执行时间,您就会看到。