

 从补丁 198 开始，Amazon Redshift 将不再支持创建新的 Python UDF。现有的 Python UDF 将继续正常运行至 2026 年 6 月 30 日。有关更多信息，请参阅[博客文章](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)。

# 查询性能改进
<a name="query-performance-improvement-opportunities"></a>

以下是影响 Amazon Redshift 查询性能的一些常见问题，以及诊断和解决这些问题的方法说明。

**Topics**
+ [表统计数据缺失或过时](#table-statistics-missing-or-out-of-date)
+ [嵌套循环](#nested-loop)
+ [哈希联接](#hash-join)
+ [虚影行或未提交的行](#ghost-rows-or-uncommitted-rows)
+ [未排序或排序错乱的行](#unsorted-or-mis-sorted-rows)
+ [非最优数据分配](#suboptimal-data-distribution)
+ [分配给查询的内存不足](#insufficient-memory-allocated-to-the-query)
+ [非最优 WHERE 子句](#suboptimal-WHERE-clause)
+ [谓词限制性不足](#insufficiently-restrictive-predicate)
+ [极大结果集](#very-large-result-set)
+ [大型 SELECT 列表](#large-SELECT-list)

## 表统计数据缺失或过时
<a name="table-statistics-missing-or-out-of-date"></a>

如果表统计信息缺失或过期，您可能会看到以下内容：
+ EXPLAIN 命令结果中存在警告消息。
+ STL\$1ALERT\$1EVENT\$1LOG 中存在缺失统计数据提醒事件。有关更多信息，请参阅 [查看查询警报](c-reviewing-query-alerts.md)。

要修复此问题，请运行 [ANALYZE](r_ANALYZE.md)。

## 嵌套循环
<a name="nested-loop"></a>

如果存在嵌套循环，您可能会在 STL\$1ALERT\$1EVENT\$1LOG 中看到嵌套循环提示事件。此外，您还可以通过运行[确定具有嵌套循环的查询](identify-queries-with-nested-loops.md)中的查询来识别此类事件。有关更多信息，请参阅 [查看查询警报](c-reviewing-query-alerts.md)。

要修复这一问题，请检查查询是否存在交叉联接，尽量将其删除。交叉联接是无联接条件的联接，它会导致对两个表执行笛卡尔积操作。它们通常作为嵌套循环联接运行，这是最慢的可能联接类型。

## 哈希联接
<a name="hash-join"></a>

如果存在哈希联接，您可能会看到以下内容：
+ 查询计划中的哈希和哈希联接操作。有关更多信息，请参阅 [分析查询计划](c-analyzing-the-query-plan.md)。
+ SVL\$1QUERY\$1SUMMARY 中 maxtime 值最大的段中的 HJOIN 步骤。有关更多信息，请参阅 [使用 SVL\$1QUERY\$1SUMMARY 视图](using-SVL-Query-Summary.md)。

要修复这一问题，您可以采取以下几种方法：
+ 重写查询，尽可能使用合并联接。为此，您可以指定既是分配键又是排序键的联接列。
+ 如果 SVL\$1QUERY\$1SUMMARY 中 HJOIN 步骤的行数字段值较查询中最终 RETURN 步骤中的行数值大得多，请确认您能否重写查询以基于唯一的列进行联接。当查询未联接唯一列（如主键）时，该列会增加联接中涉及的行数。

## 虚影行或未提交的行
<a name="ghost-rows-or-uncommitted-rows"></a>

如果存在虚影行或未提交的行，您可能会在 STL\$1ALERT\$1EVENT\$1LOG 中看到一个提示事件，指示虚影行过多。有关更多信息，请参阅 [查看查询警报](c-reviewing-query-alerts.md)。

要修复这一问题，您可以采取以下几种方法：
+ 检查 Amazon Redshift 控制台的**加载**选项卡，以便对任何查询表进行活动加载操作。如果您发现有处于活动状态的加载操作，请等待这些操作完成，然后再执行操作。
+ 如果没有活动加载操作，请对查询表运行 [VACUUM](r_VACUUM_command.md) 以移除已删除的行。

## 未排序或排序错乱的行
<a name="unsorted-or-mis-sorted-rows"></a>

如果存在未排序或排序错误的行，您可能会在 STL\$1ALERT\$1EVENT\$1LOG 中看到一个非常有选择性的筛选提示事件。有关更多信息，请参阅 [查看查询警报](c-reviewing-query-alerts.md)。

您也可以运行[确定具有数据偏斜或未排序行的表](identify-tables-with-data-skew-or-unsorted-rows.md)中的查询以检查查询中的任意表是否包含大片未排序的区域。

要修复这一问题，您可以采取以下几种方法：
+ 对查询表运行 [VACUUM](r_VACUUM_command.md) 以重新排序行。
+ 检查查询表的排序键，看看有无可以改进之处。在进行任何更改之前，请务必权衡查询的性能及其他重要查询和系统的整体性能。有关更多信息，请参阅 [排序键](t_Sorting_data.md)。

## 非最优数据分配
<a name="suboptimal-data-distribution"></a>

如果数据分配不佳，您可能会看到以下内容：
+ STL\$1ALERT\$1EVENT\$1LOG 中存在顺序执行、大型广播或大型分配提醒事件。有关更多信息，请参阅 [查看查询警报](c-reviewing-query-alerts.md)。
+ 对于给定步骤，处理的切片数与行数相差较大。有关更多信息，请参阅 [使用 SVL\$1QUERY\$1REPORT 视图](using-SVL-Query-Report.md)。
+ 对于给定步骤，切片的处理时间相差较大。有关更多信息，请参阅 [使用 SVL\$1QUERY\$1REPORT 视图](using-SVL-Query-Report.md)。

如果上述条件均未满足，您还可以查看查询中是否有任意表存在数据偏斜（运行[确定具有数据偏斜或未排序行的表](identify-tables-with-data-skew-or-unsorted-rows.md)中的查询）。

要修复这一问题，请查看查询中表的分布方式，看看有无任何可以改进之处。在进行任何更改之前，请务必权衡查询的性能及其他重要查询和系统的整体性能。有关更多信息，请参阅 [用于优化查询的数据分配](t_Distributing_data.md)。

## 分配给查询的内存不足
<a name="insufficient-memory-allocated-to-the-query"></a>

如果为查询分配到的内存不足，您可能会看到 SVL\$1QUERY\$1SUMMARY 中存在一个 `is_diskbased` 值为真的步骤。有关更多信息，请参阅 [使用 SVL\$1QUERY\$1SUMMARY 视图](using-SVL-Query-Summary.md)。

要修复这一问题，请临时增加查询使用的查询槽的数目，以向其分配更多的内存。工作负载管理 (WLM) 在查询队列中预留与为查询设置的并发级别相等的槽数。例如，并发级别为 5 的队列拥有 5 个槽。分配给队列的内存平均分配到每个槽。将多个槽分配给一个查询可使该查询访问所有这些槽的内存。有关如何临时增加查询的插槽的更多信息，请参阅[wlm\$1query\$1slot\$1count](r_wlm_query_slot_count.md)。

## 非最优 WHERE 子句
<a name="suboptimal-WHERE-clause"></a>

如果 WHERE 子句导致表扫描过多，您可能会在分段中看到在 SVL\$1QUERY\$1SUMMARY 中具有最高 `maxtime` 值的 SCAN 步骤。有关更多信息，请参阅 [使用 SVL\$1QUERY\$1SUMMARY 视图](using-SVL-Query-Summary.md)。

要修复这一问题，请根据最大的表的主排序列向查询添加 WHERE 子句。这种方法有助于尽量减少扫描时间。有关更多信息，请参阅 [设计表的 Amazon Redshift 最佳实践](c_designing-tables-best-practices.md)。

## 谓词限制性不足
<a name="insufficiently-restrictive-predicate"></a>

如果您的查询具有限制性不足的谓词，您可能会在分段中看到在 SVL\$1QUERY\$1SUMMARY 中具有最高 `maxtime` SCAN 步骤，且它的 `rows` 值比查询的最终 RETURN 步骤中的 `rows` 值高很多。有关更多信息，请参阅 [使用 SVL\$1QUERY\$1SUMMARY 视图](using-SVL-Query-Summary.md)。

若要解决此问题，请尝试向查询添加谓词或使现有谓词更具限制性，以缩小输出范围。

## 极大结果集
<a name="very-large-result-set"></a>

如果查询返回极大的结果集，请考虑重写查询，使用 [UNLOAD](r_UNLOAD.md) 将结果写入 Amazon S3。这种方法可充分利用并行处理的优势，从而提高 RETURN 步骤的性能。有关检查极大结果集的更多信息，请参阅[使用 SVL\$1QUERY\$1SUMMARY 视图](using-SVL-Query-Summary.md)。

## 大型 SELECT 列表
<a name="large-SELECT-list"></a>

如果您的查询有一个异常大的 SELECT 列表，您可能会看到 SVL\$1QUERY\$1SUMMARY 中的任何步骤的 `bytes` 值（与其他步骤相比）相对于 `rows` 值较高。`bytes` 值较大说明您选择了大量列。有关更多信息，请参阅 [使用 SVL\$1QUERY\$1SUMMARY 视图](using-SVL-Query-Summary.md)。

要解决此问题，请查看您正在选择的列，并查看是否可以删除任何列。