跳转至

6.8.3.14 数据倾斜处理

在使用列统计信息优化计划小节中,我们介绍了优化器所使用的均匀假设。然而,在实际场景中,数据常常并不满足均匀假设。当优化器由于估算误差过大而生成了不理想的执行计划时,我们可以借助 Hint 方式人工调整并优化该执行计划。

1 调优案例 1:Bucket 问题

TableBucket Key 上出现数据倾斜时, Workload 在不同的 BE instance 间会分布不均,今儿延长整个查询的执行时间。

TPC-HSchema 为例:假设 orders 表以 o_orderkey 作为 Bucket Key ,并且有两个 Tablet 。由于某些原因,一个 Tablet 包含了 1 亿行数据,而另一个 Tablet 仅包含 100 行数据。

当执行以下查询时时:

SQL
1
SELECT COUNT(*) FROM orders JOIN customer ON o_custkey = c_custkey;

优化器生成了 Broadcast Join ,其中 orders 表作为左表, customer 表作为右表。

执行引擎随后会对 orders 表的每个 Tablet 启动一个线程来执行 Join 。然而,由于数据分布不均,会导致其中一个线程处理了 1 亿行数据,而另一个线程只处理了 100 行数据。

在理想情况下,两个线程应各处理 50% 的数据,以实现查询效率提升一倍。针对此问题,我们可以指定使用 Shuffle Join ,让 orders 表的数据根据 o_custkey 重新分布,然后再与 customer 表进行 Join

2 调优案例 2:估行问题

优化器基于均匀假设估算过滤率。过滤行数误差偏大则会影响后续 SQL 算子的选择。

优化器在估算过滤率时,通常是基于均匀分布的假设。然而,当过滤行数的误差偏大时,则会影响到后续 SQL 算子的选择。

以下 SQL 查询为例:

SQL
1
2
3
select count(1)
from orders, customer
where o_custkey = c_custkey and o_orderdate < '1920-01-02'

在均匀分布的假设下,优化器可能会认为经过 o_orderdate < '1920-01-02' 过滤后输出的行数会少于 customer 表的行数,因此选择以 orders 表为基础构建 Hash Table

但是,如果实际数据存在倾斜,导致满足条件的 orders 数量多于 customer 表中的数量,那么更合理的选择应该是以 customer 表为基础来构建 Hash Table

为了优化查询,我们需要根据实际情况调整 SQL 语句或提示优化器使用更合适的执行计划。

改写 SQL 如下:

SQL
1
2
3
select /*+leading(orders customer)*/ count(1)
from orders, customer
where o_custkey = c_custkey and o_orderdate < '1920-01-02'