【发布时间】:2014-06-19 01:49:52
【问题描述】:
我有一个如下表(简化示例,我们有 60 多个字段):
CREATE TABLE "fact_table" (
"pk_a" bigint NOT NULL ENCODE lzo,
"pk_b" bigint NOT NULL ENCODE delta,
"d_1" bigint NOT NULL ENCODE runlength,
"d_2" bigint NOT NULL ENCODE lzo,
"d_3" character varying(255) NOT NULL ENCODE lzo,
"f_1" bigint NOT NULL ENCODE bytedict,
"f_2" bigint NULL ENCODE delta32k
)
DISTSTYLE KEY
DISTKEY ( d_1 )
SORTKEY ( pk_a, pk_b );
表格按高基数维度分布。
表格按时间顺序递增的一对字段排序。
该表包含超过 20 亿行,并使用约 350GB 的磁盘空间,都是“每个节点”。
我们的每小时内务管理涉及更新一些最近的记录(在表的最后 0.1% 内,基于排序顺序)并插入另外 100k 行。
无论我们选择何种机制,对表进行 VACUUM 处理都会变得过于繁琐:
- sort 步骤需要几秒钟
- merge 步骤需要 6 多个小时
我们可以从SELECT * FROM svv_vacuum_progress; 看到所有 20 亿行正在合并。即使前 99.9% 完全不受影响。
我们的理解是合并应该只影响:
1. 删除记录
2. 插入记录
3.以及从(1)或(2)到表尾的所有记录
我们尝试了DELETE and INSERT 而不是UPDATE,现在DML 步骤明显更快。但是VACUUM 仍然合并了所有 20 亿行。
DELETE FROM fact_table WHERE pk_a > X;
-- 42 seconds
INSERT INTO fact_table SELECT <blah> FROM <query> WHERE pk_a > X ORDER BY pk_a, pk_b;
-- 90 seconds
VACUUM fact_table;
-- 23645 seconds
事实上,VACUUM 合并了所有 20 亿条记录,即使我们只是将最后 746 行从表的末尾剪掉。
问题
对于如何避免这种巨大的VACUUM 开销,并且只有MERGE 出现在表格的最后 0.1% 上,是否有人有任何建议?
【问题讨论】:
-
您是否考虑过用最近的 0.1% 创建另一个表,进行合并,然后删除/重新插入这些行?
-
@GordonLinoff - 主表上的删除/重新插入仍然存在问题。类似的方法(我们希望不需要) 是手动分区;
fact_35保存最近 35 天的数据(我们预计会波动的窗口),fact_hist保存所有旧数据(我们希望稳定),以及将UNION ALL放在一起的视图。然后,我们每小时的内务管理将在一个小约 30 倍的表上工作,每晚将 1 天的数据“转移”到主表中。 (仅在fact_hist上插入,从不删除。) 但这会对 UNIONed 视图上的查询产生不良影响。 -
您还可以考虑使用每小时(或每天)的表格,并将它们与视图或简单地在相关时间范围内的查询合并。
-
@guy - 这在功能上与我在评论中已经描述的没有什么不同,因此仍然会对查询性能产生同样的不良影响。
-
我在 AWS 论坛上发现了这个问题。 AWS 的某个人正在对其进行调查。注意:AWS 中的
DELETE不会删除行,而是将它们标记为已删除。这就是为什么需要VACUUM来回收磁盘空间的原因。将VACUUM运行为DELETE ONLY或SORT ONLY有什么区别吗?我无法弄清楚排序和合并步骤是否仅针对其中一个选项发生。
标签: sql amazon-web-services amazon-redshift