首页 > 解决方案 > Redshift 查询性能以降低 CPU 利用率

问题描述

我想大致了解如何优化 redshift 数据库中的查询性能,我有很多连接的巨大查询,我确实理解使用 sort 和 Dist 键可以实现,但是有没有一种我们可以遵循的方法以获得一些最佳结果。

在表中查看什么以及如何在 redshift 中进行查询优化?为了制定特定的优化计划,需要寻找或接近哪些必要步骤?

任何指导都会有很大帮助

标签: amazon-web-servicesamazon-redshift

解决方案


改进了 Redshift 上的许多查询后,我可以为您指出一些事情。首先让我列出一些工具/技术,以确保您的工具箱中有这些。

  • 能够阅读和解释计划并找到预期的昂贵点
  • 知道在哪里可以找到查询“实际”执行报告
  • 了解系统表以查找连接、分布和磁盘 io 报告

因此,在了解了这些之后,让我们看看 Redshift 上的许多查询横向分布在哪里。我将尝试以帕累托顺序列出这些,但其中任何一个或组合都可能产生重大问题。

#1 - 中间查询中的胖子。加入时,可以扩展在许多折叠上操作的行数。交叉连接是一种可以发生这种情况的明确方式,但通常不会发生这种情况。如果条件连接创建多对多连接模式,则行数可以扩展。当表大小非常大并且“乘法”可以使数据大小变得荒谬时。解释计划可以显示这一点,但并非总是如此——使用 DISTINCT 和 GROUP BY 可以“隐藏”正在运行的数据集的真实大小。在您的连接树上执行 SELECT COUNT(*) 可以帮助显示它有多大。如果稍后的连接正在折叠行(查询优化器失败?),您可能还需要查看连接树的一部分。

#2 - 大量数据的分布。Redshift 是一个集群,节点通过以太网电缆连接在一起,这些连接是集群中最慢的部分。查询优化器做了很多工作来最小化需要在网络中移动的数据量。但是,它并不像您那样了解您的数据,而且并不总是做得很好。查看您获得的连接类型 - 是否需要分发?分发了多少数据?此外,分组依据(和窗口函数)需要组合行,因此可能需要重新分配才能完成。进入聚合步骤的数据集有多大?

在网络上移动大量数据会很慢。困难在于如何减少这种运动并不总是很清楚。像您所说的大型连接树在涉及“连接”数据的结果分布时可以做“奇怪”的事情。一次执行一个连接,并且这些连接发生的顺序很重要。查询优化器正在就连接的顺序以及如何组织每个连接的结果数据做出许多决定。它所做的选择基于它在表元数据中看到的内容,因此元数据的完整性很重要。WHERE 条件也会影响优化器的选择。有许多交互方式可以在这里逐项列出它们。最好的建议是查看每一步的性能,看看数据分布是否是一个因素。然后控制数据在查询执行中的分布方式。这可能意味着更改连接树,甚至将查询分解为几个具有分布集的临时表,以便最大限度地减少数据移动。

#3 过多的 IO 流量 - 虽然没有网络那么慢,但磁盘 IO 子系统通常是一个瓶颈。这体现在几个方面。您是否从磁盘读取的数据超出了需要?(元数据是最新的?)您是否需要冗余的 WHERE 子句来消除数据?(冗余 WHERE 子句是功能上不需要的,但添加后 Redshift 可以执行元数据比较,这将减少扫描时读取的数据。)数据溢出是磁盘 IO 紧张的另一种方式(这可以追溯到 #1) . 如果数据需要溢出到磁盘,它会大大降低磁盘 IO 性能。很好地使用您的元数据和 Where 子句。

现在,这三个方面经常联手扼杀你的表现。从表中读取太多行,通过网络将所有这些额外的行连接在一起,同时创建许多新行。此数据不适合内存,因此现在 Redshift 需要溢出到磁盘才能完成查询。在这些条件下,事情真的很快变慢了。

最后,我列出的这些因素是 Redshift 的集群范围的“资源”。如果一个查询占用了其中的很多,那么同时运行的其他查询就更少了。经常发生的情况是,集群上的查询编写者遵循相似的模式(好或坏),当他们的模式在一个轴上代价高昂时,他们的许多查询在同一轴上代价高昂。这显示为在单独运行时工作“正常”但在其他人使用集群时非常糟糕的查询。这通常意味着许多查询有助于在某些有限资源上将集群“推到边缘”。您可以查看系统表以查看聚合的 IO 或网络流量以了解这些影响。

好的查询是:

  • 在执行过程中不要做很多新的“行”(中间不要胖)
  • 将大型数据集保留在“节点上”,并且仅在数据大幅缩减后才重新分配数据
  • 不要从磁盘读取超过必要的数据并且不要溢出

问题是做所有这些并不总是可能的,诀窍是不要过度订阅你拥有的集群资源。


推荐阅读