我有一个表格如下(简化示例,我们有超过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行。
无论我们选择哪种机制,真空表都变得过于繁琐:
- 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)
你多久经常把桌子拿走?长时间如何影响你?我们的加载处理在VACUUM期间继续运行,我们从未遇到任何性能问题。基本上它并不重要,因为我们只是继续运行BAU。
我也发现我们不需要经常对我们的大桌子进行VACUUM。每周一次绰绰有余。您的用例可能对性能非常敏感,但我们发现查询时间在正常变化范围内,直到表格超过90%未分类。
如果您发现有明显的性能差异,您是否考虑使用最近和历史表(如果需要,在UNION视图内)?这样你可以VACUUM小的&#34;最近&#34;快点。
答案 1 :(得分:0)
无法在评论部分修复,因此将其发布为答案
我想现在,如果SORT键在时间序列表中是相同的,并且你有一个UNION ALL视图作为时间序列视图并且性能仍然很差,那么你可能想要一个带有显式过滤器的时间序列视图结构如
create or replace view schemaname.table_name as
select * from table_20140901 where sort_key_date = '2014-09-01' union all
select * from table_20140902 where sort_key_date = '2014-09-02' union all .......
select * from table_20140925 where sort_key_date = '2014-09-25';
还要确保在每次加载后在排序键上的所有这些表上收集统计信息,并尝试对其运行查询。如果您使用任何过滤器值,它应该能够将任何过滤器值下推到视图中。加载后的一天结束,只需在当天的桌子上运行VACUUM SORT或全真空,这应该快得多。
如果您在上述测试后仍然遇到任何问题,请告诉我。