Redshift 中的 sortkey 在内部是如何工作的?

How does sortkey in Redshift work internally?

总的来说,我是 Redshift 和数据仓库的初学者。

当数字或时间戳列被指定为 sortkey 时,Redshift DBMS 是否在查询期间使用二进制搜索来尽可能高效地找到所需的行?

我觉得了解更多这方面的知识会提高我的 table 设计技能。

Amazon Redshift 是一个列式数据存储,这意味着每个列都是单独存储的。这对于宽表非常有用,因为 Redshift 只需要读入查询中专门使用的列。数据库查询中最耗时的部分是磁盘访问,因此任何 reduces/avoids 磁盘访问都是好事。

数据存储在磁盘上时,存储在1MB的磁盘块中。每列可以消耗多个块,每个块只包含与一列相关的数据。 Redshift 为每个块保留了一个 Zone Map,它存储了存储在块中的最小值和最大值。例如,如果查询正在搜索 2021 年的数据并且 Redshift 知道特定块的时间戳列在 2018 年有最大值,它不需要从磁盘读取块检查内容。这大大减少了查询时间。

数据存储在基于所选 Compression Encoding 的块中。这些是减少数据存储 space 的非常聪明的技术。例如,如果列包含国家列表,并且行按国家/地区的字母顺序排序,则 Redshift 可以简单地存储块包含 Jamaica x 63, then Japan x 104, then Jordan x 26 的事实。这可能只需要 24 个字节来存储 193 行数据,并且不要忘记每个块的大小为 1MB。因此,压缩减少了检索数据所需的磁盘访问量,再次使查询速度更快。

回答有关 Redshift 如何找到所需行的问题:

  • 如果在 WHERE 语句中使用 SORTKEY,则 Redshift 可以快速找到可能包含所需数据的相关块。我不确定它是否通过二进制搜索来做到这一点。
  • 如果 WHERE 语句 使用 SORTKEY,则查找正确的行效率不高,因为磁盘上的许多块可能包含与 WHERE 声明在各个列中,因为它们没有排序在一起。这会降低查询效率。
  • Redshift 仍然可以 'skip-over' 不包含所有列的区域映射中匹配数据的块,避免从磁盘读取这些块的需要。此外,对各种列进行压缩可以减少需要从磁盘读取的块数。

Amazon Redshift的一般规则是:

  • DISTKEY 设置为 JOIN
  • 中最常用的列
  • SORTKEY 设置为 WHERE
  • 中最常用的列

参见:Tuning query performance - Amazon Redshift