设计查询的 Amazon Redshift 最佳实践 - Amazon Redshift
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

设计查询的 Amazon Redshift 最佳实践

要最大程度地提高查询性能,请在创建查询时遵循这些建议:

  • 根据最佳实践设计表,为查询性能提供坚固的基础。有关更多信息,请参阅设计表的 Amazon Redshift 最佳实践

  • 避免使用 select *。仅包含您需要的列。

  • 使用 CASE 条件表达式 执行复杂聚合,而不是从同一表多次选择。

  • 除非绝对必要,否则,不要使用交叉联接。这些没有联接条件的联接会导致两个表的笛卡尔积。交叉联接通常作为嵌套循环联接运行,这是最慢的联接类型。

  • 如果查询中有一个表只用于谓词条件并且子查询返回的行数较少 (不足 200 行),可以使用子查询。下面的示例使用子查询来避免联接 LISTING 表。

    select sum(sales.qtysold) from sales where salesid in (select listid from listing where listtime > '2008-12-26');
  • 使用谓词尽可能限制数据集。

  • 在谓词中,尽可能使用成本最低的运算符。比较条件 运算符优先于 LIKE 运算符。LIKE 运算符优先于 SIMILAR TOPOSIX 运算符

  • 避免在查询谓词中使用函数。如果使用函数,则需要大量的行来解析查询的中间步骤,从而增加查询成本。

  • 如果可能,请使用 WHERE 子句限制数据集。查询计划程序可以使用行顺序来帮助确定哪些记录与条件匹配,从而不必扫描大量磁盘数据块。如果没有它,查询执行引擎必须完全扫描参与的列。

  • 添加谓词以筛选参与联接的表(即使谓词应用相同的筛选条件)。查询返回相同的结果集,但 Amazon Redshift 能够在扫描步骤前筛选联接表,然后高效地跳过对这些表数据块的扫描。如果对在联接条件中使用的列进行筛选,则无需指定冗余筛选条件。

    例如,假设您需要联接 SALESLISTING 来查找在 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 命令和查找 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