数据分布与倾斜
Apache Cloudberry 依赖于跨 Segment 的均匀数据分布。
在 MPP(大规模并行处理)的无共享(shared nothing)架构中,一个查询的总体响应时间取决于所有 Segment 的完成时间。整个系统的速度取决于最慢的那个 Segment。如果数据发生倾斜,拥有更多数据的 Segment 将需要更长的时间来完成任务。因此,每个 Segment 都必须拥有大致相等的行数,并执行大致相同的处理工作量。如果某个 Segment 需要处理的数据量远超其他 Segment,就可能导致性能下降和内存不足的情况。
在连接(join)大表时,优化的分布至关重要。要执行连接操作,匹配的行必须位于同一个 Segment 上。如果数据没有按照相同的连接列进行分布,那么其中一个表所需的行就会被动态地重新分发到其他 Segment。在某些情况下,系统会执行广播(broadcast motion)操作,即每个 Segment 将其各自的行发送给所有其他 Segment;而不是执行重分布(redistribution motion)操作,即每个 Segment 对数据进行重新哈希计算,并根据哈希键将行发送到相应的 Segment。
本地连接(Co-located Join)
使用哈希分布将表行均匀地分布到所有 Segment,并实现本地连接,可以带来显著的性能提升。当要连接的行位于同一个 Segment 上时,大部分处理都可以在该 Segment 实例内部完成。这种连接被称为“本地连接”或“同位连接”(co-located join)。本地 连接可以最大限度地减少数据移动;每个 Segment 独立于其他 Segment 运行,无需网络流量或 Segment 间的通信。
要为经常连接的大表实现本地连接,你需要将这些表按照相同的列进行分布。本地连接要求连接操作的两端都按照相同的列(并以相同的顺序)进行分布,并且分布子句中的所有列都在连接表时被使用。分布列还必须是相同的数据类型——尽管某些不同数据类型的值可能看起来表示相同,但它们的存储方式不同,哈希值也不同,因此它们会被存储在不同的 Segment 上。
数据倾斜
数据倾斜可能是由于选择了错误的分布键,或执行了单行插入(single tuple insert)或复制操作,从而导致数据分布不均。数据倾斜发生在表级别,通常是查询性能不佳和内存不足问题的根本原因。倾斜的数据不仅影响扫描(读取)性能,还会影响所有其他的查询执行操作,例如连接(join)和分组(group by)操作。
在初次加载数据后,验证分布以确保数据均匀分布,这一点非常重要。同样重要的是,在增量加载后要持续验证分布情况。
以下查询显示了每个 Segment 的行数,以及行数的最大值和最小值之间的差异:
SELECT 'Example Table' AS "Table Name",
max(c) AS "Max Seg Rows", min(c) AS "Min Seg Rows",
(max(c)-min(c))*100.0/max(c) AS "Percentage Difference Between Max & Min"
FROM (SELECT count(*) c, gp_segment_id FROM facts GROUP BY 2) AS a;
gp_toolkit
模式(schema)提供了两个视图,你可以用它们来检查数据倾斜。
gp_toolkit.gp_skew_coefficients
视图通过计算存储在每个 Segment 上的数据的变异系数(CV)来显示数据分布的倾斜情况。skccoeff
列显示了变异系数(CV),其计算方法是标准差除以平均值。它同时考虑了数据序列的平均值和围绕平均值的变异性。这个值越低越好,值越高表示数据倾斜越严重。gp_toolkit.gp_skew_idle_fractions
视图通过计算表扫描期间系统空闲时间的百分比来显示数据分布的倾斜情况,这是计算倾斜的一个指标。siffraction
列显示了在表扫描期间系统空闲时间的百分比。这个指标反映了数据分布不均或查询处理倾斜的情况。例如,值0.1
表示 10% 的倾斜,值0.5
表示 50% 的倾斜,依此类推。倾斜度超过 10% 的表,应该重新评估其分布策略。