6.8.3.7 使用列统计信息优化计划¶
优化器在 CBO
阶段,利用列统计信息,能够做出更为精准的估算,进而找到代价更小的执行计划( plan
)。为了有效利用统计信息, Doris
首先需要执行统计信息的收集工作,具体请参考统计信息收集。
在统计信息的辅助下,我们能够更为准确地估算出算子输出的行数,这包括过滤、 Join
以及聚合等操作。下面,我们将通过案例来演示 Doris
如何使用列统计信息优化计划。
Tip
以下案例数据均通过 TPC-H
工具生成。如需了解 TPC-H Benchmark
详情可前往官网查看
1 案例 1:过滤¶
查询语句如下:
SQL | |
---|---|
1 |
|
在没有统计信息的情况下,优化器只能依据经验参数来估算 o_orderdate < '1990-01-01'
这一条件过滤后的行数,例如,可能会简单地将过滤结果估算为 orders
表行数的一半。
然而,通过执行 analyze table orders
命令,优化器便能够获取到 o_orderdate
列的最小值,即 '1992-01-01'
。因此,优化器能够准确地判断出过滤后的行数实际上并没有减少。
2 案例 2:Join 操作¶
Hash Join
是最常用的 Join
算法。该算法会利用一个表来构建 Hash Table
,而另一个表则作为 Probe
表进行匹配。由于构建 Hash Table
的代价远高于 Probe
操作代价,因此应选择行数较少的表来构建 Hash Table
。
在 Doris
中,规定 Join
操作的右表用于构建 Hash Table
,而左表则作为 Probe
表。已知 orders
表的行数为 150,000
,而 customer
表的行数为 15,000
,两者相差 10
倍。
查询语句如下:
SQL | |
---|---|
1 |
|
在没有统计信息的情况下,我们可能会估算过滤后的 orders
表行数为原表的一半,即 75,000
行,这仍然比 customer
表的行数多。因此, Join
的顺序会被确定为 orders join customer
,即 customer
表构建 Hash Table
, orders
表作为 Probe
表。
然而,如果拥有统计信息,优化器便能知道 o_orderdate
列的最小值是 '1992-01-01'
,因此会估算出过滤后的结果为 0
行,这显然比 customer
表的行数要少。于是, Join
的顺序会调整为 customer join orders
。
在实际测试中,采用统计信息生成的执行计划相较于未使用统计信息的执行计划,其执行效率增加了 40%
。
3 案例 3:均匀假设¶
在实际业务场景中,数据分布往往并不均匀。以订单日期 o_orderdate
为例,尽管在使用统计信息估算查询计划成本时,优化器可能会采用均匀假设,即假设每年的订单量相同,但实际上, 1992
年的订单量可能会显著超过其他年份的总和。具体来说,如果 o_orderdate
的范围是 '1992-01-01'
到 '1998-08-02'
,一共 8
年,那么在均匀假设下,优化器会估算 o_orderdate < '1993-01-01'
的过滤率为 1/8
。然而,这种假设很可能导致优化器低估了实际过滤后的行数,进而影响到后续 Join
操作中表的选择顺序。
为了更准确地评估查询性能并优化 Join
顺序,我们需要查看执行计划( Profile
)中记录的实际过滤行数。在此基础上,还可以在 SQL
中添加 Hint
,以指导优化器选择更合适的 Join
顺序。
4 案例 4:无列统计信息¶
在某些特定场景下,可能会出现无法收集列统计信息的情况。例如,当查询涉及外部表时、当数据量极为庞大,或者收集统计信息的成本过高时。面对这种情况,优化器将转而依据表的行数,并通过启发性规则来生成执行计划( plan
)。通常,在缺少统计信息的情况下,优化器倾向于生成一个左深树的执行计划。