Abh*_*nav 2 amazon-web-services amazon-redshift
我们有一个 2 节点 Redshift 集群,其中有一个包含大约 100M 记录的表。我们将时间戳列标记为排序键 - 因为查询始终受到时间限制。但是,我们的用例要求结果必须按降序排序(在排序键上)。
经过一些基准测试后,我们注意到平均时间约为 10 秒。然而,当取消反向排序后,平均时间降至 1 秒以下。
是否可以将排序键的顺序反转为降序?官方文档似乎没有表明这是可能的。不过,我在创建新表时尝试将其放入:
sortkey(start_time DESC)
Run Code Online (Sandbox Code Playgroud)
没有错误,但似乎没有任何效果。
编辑:添加了查询的 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;
Run Code Online (Sandbox Code Playgroud)
结果:
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))
Run Code Online (Sandbox Code Playgroud)使用 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
Run Code Online (Sandbox Code Playgroud)
结果:
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))
Run Code Online (Sandbox Code Playgroud)Amazon Redshift表SORTKEY上的 区域地图 用于通过使用区域地图来提高查询效率。它的目的不是对数据进行排序以匹配查询。
Amazon Redshift 将数据以 1MB 块的形式存储在磁盘上。每个块包含与一个表的一列相关的数据,并且该列的数据可以占用多个块。块可以被压缩,因此它们通常包含超过 1MB 的数据。
磁盘上的每个块都有一个关联的区域映射,用于标识该块中所存储列的最小值和最大值。这使得 Redshift 能够跳过不包含相关数据的块。例如,如果SORTKEY是时间戳并且查询具有WHERE将数据限制为特定日期的子句,则 Redshift 可以跳过所需日期不在该块内的任何块。
一旦 Redshift 找到包含所需数据的块,它将读取这些块来执行查询。
在查看您的EXPLAIN计划时,第二个示例显然有一个额外的SORT步骤。查询优化器似乎知道您正在对与 匹配的列进行排序SORTKEY,因此在第一个示例中会跳过排序。当数据附加到表中时,这很常见,导致更新的数据出现在列的末尾。
为您提供一些选择:
如果您总是进行新的数据加载,则可以添加一个与日期相反的新列(例如,从 3000 年减去存储的日期的间隔)。使用它作为SORTKEY,数据将被反向存储。真实日期列的区域地图也将方便地进行反向排序。
如果您不断加载新数据,则最新数据将附加到列的末尾,因此无论如何您都无法轻松地对数据进行反向排序。
使用较小的日期范围。上面的查询将结果限制在六个月的范围内,返回 1,306,585 行。然后查询对其进行排序,并将结果限制为最近的 20 个。如果减小日期范围(例如,仅一天),则检索到的数据越少,排序将运行得更快,查询也会更快。考虑到这么多行,平均每天有 7000 多条记录,因此对于LIMIT 20.
不要使用SELECT *——它会导致从磁盘读取更多块(因为每一列都存储在单独的块中)。通过仅查询实际需要的列,将减少磁盘访问并且查询运行得更快。
| 归档时间: |
|
| 查看次数: |
3226 次 |
| 最近记录: |