我们有一个2节点的Redshift集群,其中一个表有大约100M的记录。我们将timestamp列标记为sortkey - 因为查询总是受时间限制。但是,我们的用例要求结果必须按降序排序(在sortkey上)。
经过一些基准测试后,我们注意到平均时间约为10秒。但是,当删除反向排序时,平均时间降至1秒以下。
是否可以将sortkey的顺序颠倒为降序?官方文件似乎并未表明这是可能的。但是我在创建新表时尝试了这个:
sortkey(start_time DESC)
没有错误,但似乎没有任何影响。
编辑:在查询中添加了EXPLAIN语句的结果。
使用order_by ASC的查询
explain select * from kcdr_sr_desc where user_id=396747 and start_time > '2016-01-01' and start_time < '2016-07-01' order by start_time limit 20;
结果:
XN Limit (cost=0.00..10.86 rows=20 width=300)
-> XN Merge (cost=0.00..709235.56 rows=1306585 width=300)
Merge Key: start_time
-> XN Network (cost=0.00..709235.56 rows=1306585 width=300)
Send to leader
-> XN Seq Scan on kcdr_sr_desc (cost=0.00..709235.56 rows=1306585 width=300)
Filter: ((user_id = 396747) AND (start_time > '2016-01-01 00:00:00'::timestamp without time zone) AND (start_time < '2016-07-01 00:00:00'::timestamp without time zone))
使用order_by DESC的查询
explain select * from kcdr_sr_desc where user_id=396747 and start_time > '2016-01-01' and start_time < '2016-07-01' order by start_time desc limit 20
结果:
XN Limit (cost=1000000841967.42..1000000841967.47 rows=20 width=300)
-> XN Merge (cost=1000000841967.42..1000000845233.88 rows=1306585 width=300)
Merge Key: start_time
-> XN Network (cost=1000000841967.42..1000000845233.88 rows=1306585 width=300)
Send to leader
-> XN Sort (cost=1000000841967.42..1000000845233.88 rows=1306585 width=300)
Sort Key: start_time
-> XN Seq Scan on kcdr_sr_desc (cost=0.00..709235.56 rows=1306585 width=300)
Filter: ((user_id = 396747) AND (start_time > '2016-01-01 00:00:00'::timestamp without time zone) AND (start_time < '2016-07-01 00:00:00'::timestamp without time zone))
答案 0 :(得分:1)
Amazon Redshift表上的SORTKEY
用于通过使用区域地图来提高查询效率。它不打算对数据进行排序以匹配查询。
Amazon Redshift将数据存储在1MB块的磁盘上。每个块包含与一个表的一列相关的数据,并且来自该列的数据可以占用多个块。块可以被压缩,因此它们通常包含超过1MB的数据。
磁盘上的每个块都有一个关联的区域映射,用于标识该块中存储的列的最小值和最大值。这使Redshift能够跳过不包含相关数据的块。例如,如果SORTKEY
是时间戳并且查询具有将数据限制为特定日期的WHERE
子句,则Redshift可以跳过所需日期不在该块内的任何块。< / p>
一旦Redshift找到具有所需数据的块,它将读取这些块以执行查询。
在查看您的EXPLAIN
计划时,第二个示例显然有一个额外的SORT
步骤。看起来查询优化器知道您正在对与SORTKEY
匹配的列进行排序,因此在第一个示例中跳过了排序。这通常是附加到表的数据,导致更新的数据出现在列的末尾。
为您提供的一些选项:
如果您总是在进行新的数据加载,则可以添加与日期相反的新列(例如,从3000年减去存储日期的时间间隔) 。将其用作SORTKEY
,数据将反向存储。实际日期列的区域地图也可以方便地进行反向排序。
如果您不断加载新数据,最新数据将附加到列的末尾,因此无论如何都无法轻松地对数据进行反向排序。
使用较小的日期范围。上述查询将结果限制在六个月的范围内,返回1,306,585行。然后查询将结果限制为最近20的结果。如果减少日期范围(例如减少到一天),将检索的数据越少,排序运行得越快,查询将越快。鉴于行数很多,每天平均有7000多条记录,因此对LIMIT 20
来说应该足够了。
不要使用SELECT *
- 它会导致从磁盘读取更多块(因为每列都存储在一个单独的块中)。通过仅查询实际需要的列,可以减少磁盘访问,并且查询运行得更快。