【问题标题】:Convert indexes to sortkeys Redshift将索引转换为排序键 Redshift
【发布时间】:2021-01-02 22:28:29
【问题描述】:
  1. 区域地图是否只存在于内存中?或者它从永久存储的磁盘中填充到内存中?它是与 1MB 块一起存储的,还是单独存储的?
  2. 我们正在从 oracle 迁移到 redshift,有很多索引可以满足报告需求。 Redshift 中与 index 最接近的等价物是 sortkeys。对于一堆表,所有索引的列总数在15-20之间(有些是复合索引,有些是单列索引)。交错键似乎是最合适的,但交错排序键中的列不能超过 8 个。但是如果我使用复合排序键,它不会有效,因为查询可能没有前缀列。 在这种情况下,一般建议是什么——使用哪种类型的排序键?如何将许多索引从 rdbms 转换为 redshift 中的排序键?
  3. 身份列、日期和时间戳等高基数列是否不适合交错密钥?复合排序键是否相同?需要考虑交错排序键的任何缺点?

【问题讨论】:

  • 我要指出@BillWeiner 所说的一些东西:交错排序键的收益递减。根据我使用 Redshift 和其他并行数据库(可追溯到 1990 年代)的经验,只要让数据库分发查询,您通常会获得更好的性能。这并不意味着完全摆脱排序键,而是要认识到它们并不直接等同于索引。

标签: amazon-web-services amazon-redshift


【解决方案1】:

您提出的问题是正确的,所以让我们一次解决一个问题。首先,区域地图位于领导节点并存储在磁盘上,表数据存储在计算节点上。它们彼此分开。 zonemap 存储表中每 1MB 块的每列的最小值和最大值。无论一列是否在您的排序键列表中,都会有该块的区域地图数据。当列出现在 WHERE 子句中时,Redshift 将首先与区域地图数据进行比较,以确定查询是否需要该块。如果不需要某个块,则不会从磁盘读取它,从而显着提高超大表的性能。我称之为“阻止拒绝”。几个关键点 - 这真的只对数以千万计的行以及有选择性 WHERE 谓词的表产生影响。

因此,您有许多报告,每个报告都从不同​​方面查看数据 - 很常见。您希望所有这些都能正常工作,对吗?现在首先要注意的是,每个表都可以有自己的排序键,它们没有链接。重要的是排序键的选择如何影响您将用作 WHERE 子句的列的区域图中的最小值和最大值。使用复合排序键,您必须考虑后面的键会对块的组成产生什么影响——在第三个或第四个键之后不会有太大影响。这受数据顺序性的影响很大,但你明白了。好消息是,对一列进行排序会影响所有列的区域图,因此您不必总是在排序键列表中有一列才能获得好处。

复合排序键与交错排序键的问题是一个复杂的问题,但请记住,您希望尽可能频繁地获得高水平的块拒绝(并且在最大的表上)。当不同的查询有不同的 WHERE 谓词时,要获得良好的排序键组合来实现这一点可能会很棘手。一般来说,复合排序键更容易理解并且对表维护的影响更少。您可以检查区域图并查看您的排序键选择有什么影响,并就如何调整做出明智的决定。如果存在序数较低的列,则将它们放在首位,以便下一个排序键可以影响整个行顺序,从而为这些后面的键生成具有不同值范围的块。由于这些原因,我喜欢复合键而不是交错键,但在某些情况下,交错键会改善情况。当所有列的序数都很高并且它们都同样重要时,交错可能是正确的答案。我通常会了解尝试优化复合键的数据,即使我最终使用交错键,我也可以明智地选择我想要排序键中的哪些列。

只有一些指标可以帮助您做出选择。 Redshift 可以在一个块中存储 200,000 个行元素,我已经看到每个块有超过 2M 个元素的列。块分布在整个集群中,因此您需要大量行来填充足够多的块,甚至可以拒绝其中的大部分。如果您有一个包含 500 万行的表,并且您正在为排序键出汗,那么您就会陷入困境。 (是的,排序会影响查询的其他方面,比如加入,但这些都是亚秒级的改进,不会影响性能。)压缩会对每个块的行元素数量产生巨大影响,因此在一个数据块中表示多少行。区域图中的条目。这可能会增加块拒绝,但会增加扫描整个表所需的读取数据 - 您需要权衡取舍以确保您获胜(1 个查询变快 10 个变慢可能不是一个好的权衡)。

您关于序数的问题是一个很好的问题。如果我首先在复合排序键列表中对我的高序列进行排序,这将设置行的整体顺序,可能会使所有其他排序键无能为力。但是,如果我首先按低序列排序,那么其他排序键就有很大的权力来改变行的顺序,从而改变 zonemap 的内容。例如,如果我的 Col_A 只有 100 个唯一值,而 Col_B 是分辨率为 1 微秒的时间戳。如果我首先按 Col_B 排序,则所有行都可能仅通过在此列上排序。但是,如果我首先按 Col_A 排序,则会有许多具有相同值的行,而后面的 sortkey (Col_B) 可以对这些行进行排序。 Interleaved 的工作方式相同,只是哪一列是“第一”列由表的区域更改。如果我在上面相同的 Col_A 和 Col_B 上交错排序(只有 2 个排序键),那么一半的表将首先由 Col_A 排序,一半由 Col_B 排序。对于这个例子,Col_A 有一半的时间是没用的——不是最好的答案。交错排序只是修改哪一列用作整个表中的第一个排序键(如果使用更多键,则为第二个和第三个)。排序键中的高序数使得后面的排序键不那么强大,并且这与排序样式无关 - 只是交错改变了哪些列是早期的,哪些列是延迟的。

因为排序键的序数可能是在许多 WHERE 谓词中获得块拒绝的重要因素,所以通常将派生列添加到表中以保存其他列的序数较低的版本。在上面的示例中,我可能会将 Col_B2 添加到表中,并且如果只保存 Col_B 的年月(月份截断日期)。我会在排序键列表中使用 Col_B2,但我的查询仍将引用 Col_B。它“粗略地”根据 Col_B 进行排序,因此如果 Col_A 在排序键列表的后面出现,它可以具有一些排序能力。这是在迁移 Redshift 时更改数据模型的常见原因。

同样重要的是,针对事实表列写入的“阻止拒绝”WHERE 子句在连接后不应用于维度表列。 Zonemap 信息在查询开始执行之前读取并在领导节点上完成 - 它无法通过连接查看。另一个数据模型更改是将一些关键信息非规范化到事实表中,以便这些常见的 where 谓词可以应用于事实表和区域图。

对不起,我花了一年时间优化这个主题。我希望这对您有用,如果有任何不清楚的地方请联系(我希望您已经整理好 DISTKEYS :))。

【讨论】:

  • 太棒了,非常感谢比尔解释得这么好。这为如何构建我的排序键提供了更多见解,是的,我很擅长使用 distkeys :-)
  • 很高兴听到。这就是我所做的 - 帮助团队充分利用 Redshift。请记住,在最高级别排序键(以及区域映射)会减少磁盘读取,而 dist 键会减少网络流量。如果您不超额订阅这些资源,Redshift 很快就会被淘汰,如果您确实超额订阅它们,您将度过一段糟糕的时光。和平。
猜你喜欢
  • 2018-03-18
  • 1970-01-01
  • 1970-01-01
  • 2018-12-18
  • 2014-02-04
  • 2019-02-11
  • 1970-01-01
  • 1970-01-01
  • 2014-12-09
相关资源
最近更新 更多