本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
设计 Amazon Redshift 查询的最佳实践
本节概述了设计查询的最佳实践。我们建议您遵循本节中的最佳实践,以实现最佳的查询性能和效率。
避免使用 SELECT* FROM 语句
我们建议您避免使用该SELECT * FROM
语句。相反,请务必列出要分析的列。这减少了查询执行时间,并减少了亚马逊 Redshift Spectrum 查询的扫描成本。
应避免的事情示例
select * from sales;
最佳实践示例
select sales_date, sales_amt from sales;
识别查询问题
我们建议您查看 STL_ALERT_EVENT_LOG 视图,找出并更正查询中可能存在的问题。
获取有关您的查询的摘要信息
我们建议您使用 SVL_QUERY_SUMMARY 和 SVL_QUERY_REPORT 视图来获取有关查询的摘要信息。您可以使用这些信息来优化查询。
避免交叉连接
除非绝对必要,否则我们建议您避免使用交叉联接。如果没有连接条件,交叉连接会产生两个表的笛卡尔乘积。交叉联接通常以嵌套循环联接(可能的联接类型中最慢的一种)的形式运行。
应避免的事情示例
select c.c_name, n.n_name from tpch.customer c, tpch.nation n;
最佳实践示例
select c.c_name, n.n_name from tpch.customer c, join tpch.nation n on n.n_nationkey = c.c_nationkey;
避免在查询谓词中使用函数
我们建议您避免在查询谓词中使用函数。在查询谓词中使用函数可能会对性能产生负面影响,因为函数通常会给每行增加额外的处理开销,并减慢查询的整体执行速度。
应避免的事情示例
select sum(o_totalprice) from tpch.orders where datepart(year, o_orderdate) = 1992;
最佳实践示例
select sum(o_totalprice) from tpch.orders where o_orderdate between '1992-01-01' and '1992-12-31';
避免不必要的演员阵容转换
我们建议您避免对查询使用不必要的转换转换,因为转换数据类型需要时间和资源,并且会减慢查询的执行速度。
应避免的事情示例
select sum(o_totalprice) from tpch.orders where o_ordertime::date = '1992-01-01';
最佳实践示例
select sum(o_totalprice) from tpch.orders where o_ordertime between '1992-01-01 00:00:00' and '1992-12-31 23:59:59';
使用 CASE 表达式进行复杂聚合
我们建议您使用 C ASE 表达式来执行复杂的聚合,而不是多次从同一个表中进行选择。
应避免的事情示例
select sum(sales_amt) as us_sales from sales where country = 'US'; select sum(sales_amt) as ca_sales from sales where country = 'CA';
最佳实践示例
select sum(case when country = 'US' then sales_amt end) as us_sales, sum(case when country = 'CA' then sales_amt end) as ca_sales from sales;
使用子查询
如果查询中的一个表仅用于谓词条件,而子查询返回的行数很少(少于大约 200),我们建议您使用子查询。
应避免的事情示例
如果子查询返回的行数少于 200 行:
select sum(order_amt) as total_sales from sales where region_key IN (select region_key from regions where state = 'CA');
最佳实践示例
如果子查询返回的行数大于或等于 200 行:
select sum(o.order_amt) as total_sales from sales o join regions r on r.region_key = o.region_key and r.state = 'CA';
使用谓词
我们建议您使用谓词来尽可能地限制数据集。在 SQL 中使用谓词来筛选和限制查询中返回的数据。通过在谓词中指定条件,您可以根据指定的条件指定查询结果中必须包含哪些行。这允许您仅检索自己感兴趣的数据,并提高查询的效率和准确性。有关更多信息,请参阅亚马逊 Redshift 文档中的条件。
添加谓词以筛选带有联接的表
我们建议您添加谓词来筛选参与联接的表,即使谓词应用相同的筛选条件也是如此。在 SQL 中使用谓词筛选带有联接的表可以减少必须处理的数据量并减小中间结果集的大小,从而提高查询性能。通过在WHERE
子句中指定联接操作的条件,查询执行引擎可以在联接前删除与条件不匹配的行。这会使结果集变小,查询执行速度更快。
应避免的事情示例
select p.product_name, sum(o.order_amt) from sales o join product p on r.product_key = o.product_key where o.order_date > '2022-01-01';
最佳实践示例
select p.product_name, sum(o.order_amt) from sales o join product p on p.product_key = o.product_key and p.added_date > '2022-01-01' where o.order_date > '2022-01-01';
使用最便宜的运算符作为谓词
在谓词中,尽可能使用最便宜的运算符。比较条件运算符比 LIK E 运算符更可取。 LIKE
运算符仍然比 “类似” 或 “POSIX” 运算符更可取。
在 GROUP BY 子句中使用排序键
在GROUP BY
子句中使用排序键,以便查询计划器可以使用更有效的聚合。如果查询的GROUP
BY
列表仅包含排序键列,其中一个也是分配键,则该查询可能有资格进行单阶段聚合。GROUP BY
列表中的排序键列必须包括第一个排序键,然后是要按排序键顺序使用的其他排序键。
利用物化视图
如果可能,请通过将复杂的代码替换为物化视图来重写查询,这将显著提高查询的性能。有关更多信息,请参阅 Amazon Redshift 文档中的在 Amazon Redshift 中创建实体化视图。
小心使用 GROUP BY 和 ORDER BY 子句中的列
如果同时使用GROUP BY
和ORDER BY
子句,请确保在和GROUP BY
子句中按相同顺序排列列。ORDER BY
GROUP BY
隐含地要求对数据进行排序。如果您的ORDER
BY
子句不同,则必须对数据进行两次排序。
应避免的事情示例
select a, b, c, sum(d) from a_table group by b, c, a order by a, b, c
最佳实践示例
select a, b, c, sum(d) from a_table group by a, b, c order by a, b, c