

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

# 设计查询的 Amazon Redshift 最佳实践
<a name="c_designing-queries-best-practices"></a>

要最大程度地提高查询性能，请在创建查询时遵循这些建议：
+ 根据最佳实践设计表，为查询性能提供坚固的基础。有关更多信息，请参阅 [设计表的 Amazon Redshift 最佳实践](c_designing-tables-best-practices.md)。
+ 避免使用 `select *`。仅包含您需要的列。
+ 使用 [CASE 条件表达式](r_CASE_function.md) 执行复杂聚合，而不是从同一表多次选择。
+ 除非绝对必要，否则，不要使用交叉联接。这些没有联接条件的联接会导致两个表的笛卡尔积。交叉联接通常作为嵌套循环联接运行，这是最慢的联接类型。
+ 如果查询中有一个表只用于谓词条件并且子查询返回的行数较少 (不足 200 行)，可以使用子查询。下面的示例使用子查询来避免联接 LISTING 表。

  ```
  select sum(sales.qtysold)
  from sales
  where salesid in (select listid from listing where listtime > '2008-12-26');
  ```
+ 使用谓词尽可能限制数据集。
+ 在谓词中，尽可能使用成本最低的运算符。[比较条件](r_comparison_condition.md) 运算符优先于 [LIKE](r_patternmatching_condition_like.md) 运算符。LIKE 运算符优先于 [SIMILAR TO](pattern-matching-conditions-similar-to.md) 或 [POSIX 运算符](pattern-matching-conditions-posix.md)。
+ 避免在查询谓词中使用函数。如果使用函数，则需要大量的行来解析查询的中间步骤，从而增加查询成本。
+ 如果可能，请使用 WHERE 子句限制数据集。查询计划程序可以使用行顺序来帮助确定哪些记录与条件匹配，从而不必扫描大量磁盘数据块。如果没有它，查询执行引擎必须完全扫描参与的列。
+ 添加谓词以筛选参与联接的表（即使谓词应用相同的筛选条件）。查询返回相同的结果集，但 Amazon Redshift 能够在扫描步骤前筛选联接表，然后高效地跳过对这些表数据块的扫描。如果对在联接条件中使用的列进行筛选，则无需指定冗余筛选条件。

  例如，假设您需要联接 `SALES` 和 `LISTING` 来查找在 12 月之后列出的票的销售数据并按卖家分组。两个表都按日期排序。下面的查询使用表的公共键联接这两个表，并筛选晚于 12 月 1 日的 `listing.listtime` 值。

  ```
  select listing.sellerid, sum(sales.qtysold)
  from sales, listing
  where sales.salesid = listing.listid
  and listing.listtime > '2008-12-01'
  group by 1 order by 1;
  ```

  WHERE 子句不包含针对 `sales.saletime` 的谓词，因此，执行引擎必须扫描整个 `SALES` 表。如果您知道哪些筛选条件能够减少参与联接操作的行数，则也请添加这些筛选条件。下面的示例明显地减少了执行时间。

  ```
  select listing.sellerid, sum(sales.qtysold)
  from sales, listing
  where sales.salesid = listing.listid
  and listing.listtime > '2008-12-01'
  and sales.saletime > '2008-12-01'
  group by 1 order by 1;
  ```
+ 在 GROUP BY 子句中使用排序键，以便查询计划程序可以使用更高效的聚合。如果查询的 GROUP BY 列表只包含排序键列，并且其中一列也是分配键，则查询可能适合单阶段聚合。GROUP BY 列表中的排序键列必须包含第一个排序键，然后按排序键顺序包含其他需要使用的排序键。例如，可以使用第一个排序键，第一个和第二个排序键，第一个、第二个和第三个排序键，依此类推。不能使用第一个和第三个排序键。

  您可以通过在查询的聚合步骤中运行 [EXPLAIN](r_EXPLAIN.md) 命令和查找 `XN GroupAggregate` 来确认使用单阶段聚合。
+ 如果同时使用 GROUP BY 和 ORDER BY 子句，两个子句中各列的顺序必须相同。也就是，使用下面的方法。

  ```
  group by a, b, c
  order by a, b, c
  ```

  不要使用以下方法。

  ```
  group by b, c, a
  order by a, b, c
  ```