【发布时间】:2019-01-08 22:49:34
【问题描述】:
我在 redshift DC28XL 集群中有一个大约 5.27 亿行的表。
我添加了特定的 varchar 列(称为段)作为我的 dist 键和排序键。每个段大约有 4M 行。当我对一个段 select * from table where segment ='s1'; 运行带有 where 子句的简单选择时,Redshift 总是执行顺序扫描并且需要 3 分钟以上。
有人可以帮助我避免全表扫描并将性能降低到 10 秒或更短吗?
【问题讨论】:
-
您实际上是在检查字符串吗?通过“每个段大约有 4M 行”,您的意思是
segment的每个不同值都有大约 4M 行,是吗?请注意,即使您的数据已排序,EXPLAIN 仍会显示顺序扫描——这只是有限的顺序扫描;对于未排序的数据,成本会有所不同。例如我进行了一项测试,以检查在使用和不使用时间戳作为排序键的样本集上过滤两个时间戳之间的执行差异,并且 EXPLAIN 显示了 7 倍的加速。已排序:cost=0.00..110954.75,未排序:cost=0.00..700127.12) -
我用多个更小的间隔 BETWEEN 语句(与 OR 结合)运行了相同的测试,并看到了更大的加速,大约 40 倍。
-
Redshift 存储数据的方式是以块为单位的,每个块都会为 sortkey 存储一个最小值/最大值。它仍然需要查看每个块,但它会发现它正在寻找的值不在该块的范围内,所以它会跳过它,依此类推,直到找到值在这些范围内的块。所以这就是为什么它仍然是顺序扫描,即使它实际上并不是扫描每一行。
-
是的,你是对的。段字段是 varchar,段的每个不同值大约有 4M 行。尽管它说 dist 样式是基于键的,但该表也显示出高偏差。我跑了真空并分析。我仍然得到相同的结果。
-
为什么要针对 400 万行数据执行
select *?你真的想要所有这些数据吗?运行select sum(value) where segment = 's1'可能更现实,因为它与通常针对数据仓库运行的查询类型相匹配。
标签: amazon-redshift