【问题标题】:Change order of sortkey to descending将sortkey的顺序更改为降序
【发布时间】:2016-12-30 16:38:16
【问题描述】:

我们有一个 2 节点的 Redshift 集群,其中的表包含大约 1 亿条记录。我们将时间戳列标记为排序键——因为查询总是有时间限制的。但是,我们的用例要求结果必须按降序排序(在排序键上)。

经过一些基准测试后,我们注意到平均耗时大约 10 秒。但是,去掉逆序后,平均时间降到了 1s 以下。

是否可以将排序键的顺序反转为降序?官方文档似乎没有表明这是可能的。但是我尝试在创建新表时放置它:

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))
    

【问题讨论】:

  • Redshift 中没有升序或降序排序键的概念。您的基准测试结果令我惊讶。您确定这不是由代码编译引起的吗? (docs.aws.amazon.com/redshift/latest/dg/c-query-performance.html)
  • @GuiSim 我已经在两种类型的查询中添加了 EXPLAIN 的结果 - 显然,使用 order_by 作为 DESC 的查询似乎更昂贵。如果我没记错的话 - 它会在返回结果之前对整个数据范围进行排序。

标签: amazon-web-services amazon-redshift


【解决方案1】:

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 *——它会导致从磁盘读取更多块(因为每一列都存储在一个单独的块中)。通过只查询实际需要的列,磁盘访问量会更少,查询会运行得更快。

【讨论】:

  • 只是想说第一个选项非常适合我的用例。此外,选择所需的列而不是使用 select * 也大大提高了性能。非常感谢!
猜你喜欢
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多