

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 設計 Amazon Redshift 查詢的最佳實務
<a name="best-practices-designing-queries"></a>

本節提供設計查詢的最佳實務概觀。我們建議您遵循本節中的最佳實務，以實現最佳的查詢效能和效率。

## 避免使用 SELECT \* FROM 陳述式
<a name="select-from-statement"></a>

建議您避免使用`SELECT * FROM` 陳述式。反之，一律列出要分析的資料欄。這可減少查詢執行時間，並掃描 Amazon Redshift Spectrum 查詢的成本。

**要避免的內容範例**

```
select * 
from sales;
```

**最佳實務範例**

```
select sales_date, sales_amt
from sales;
```

## 識別查詢問題
<a name="query-issues"></a>

建議您檢查 [STL\_ALERT\_EVENT\_LOG](https://docs.aws.amazon.com/redshift/latest/dg/r_STL_ALERT_EVENT_LOG.html) 檢視，以識別和修正查詢的可能問題。

## 取得查詢的摘要資訊
<a name="summary-info"></a>

我們建議您使用 [SVL\_QUERY\_SUMMARY](https://docs.aws.amazon.com/redshift/latest/dg/r_SVL_QUERY_SUMMARY.html) 和 [SVL\_QUERY\_REPORT](https://docs.aws.amazon.com/redshift/latest/dg/r_SVL_QUERY_REPORT.html) 檢視來取得查詢的摘要資訊。您可以使用此資訊來最佳化查詢。

## 避免交叉聯結
<a name="cross-joins"></a>

除非絕對必要，否則建議您避免使用跨聯結。如果沒有聯結條件，跨聯結會產生兩個資料表的笛卡兒乘積。跨聯結通常會以巢狀迴圈聯結 （最慢的可能聯結類型） 的形式執行。

**要避免的內容範例**

```
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;
```

## 避免查詢述詞中的函數
<a name="functions-query-predicates"></a>

建議您避免在查詢述詞中使用 函數。在查詢述詞中使用函數可能會對效能產生負面影響，因為函數通常會為每個資料列增加額外的處理開銷，並減慢查詢的整體執行速度。

**要避免的內容範例**

```
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';
```

## 避免不必要的轉換
<a name="cast-conversions"></a>

我們建議您避免在查詢上使用不必要的轉換轉換，因為轉換資料類型需要時間和資源，並減慢查詢執行速度。

**要避免的內容範例**

```
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 表達式進行複雜的彙總
<a name="case-expressions"></a>

我們建議您使用 [CASE 表達](https://docs.aws.amazon.com/redshift/latest/dg/r_CASE_function.html)式來執行複雜的彙總，而不是多次從相同的資料表中選取 。

**要避免的內容範例**

```
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;
```

## 使用子查詢
<a name="subqueries"></a>

如果查詢中的一個資料表僅用於述詞條件，且子查詢傳回少量資料列 （少於約 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';
```

## 使用述詞
<a name="predicates"></a>

我們建議您使用述詞來盡可能限制資料集。SQL 中使用述詞來篩選和限制查詢中傳回的資料。透過在述詞中指定條件，您可以指定哪些資料列必須根據指定的條件包含在查詢結果中。這可讓您僅擷取您感興趣的資料，並改善查詢的效率和準確性。如需詳細資訊，請參閱 Amazon Redshift 文件中的[條件](https://docs.aws.amazon.com/redshift/latest/dg/r_conditions.html)。

## 新增述詞以使用聯結篩選資料表
<a name="filter-tables-joins"></a>

我們建議您新增述詞來篩選參與聯結的資料表，即使述詞套用相同的篩選條件。使用述詞篩選具有 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';
```

## 針對述詞使用最便宜的運算子
<a name="least-expensive-operators"></a>

在述詞中，使用您可以花費最低的運算子。[比較條件](https://docs.aws.amazon.com/redshift/latest/dg/r_comparison_condition.html)運算子偏好 [LIKE](https://docs.aws.amazon.com/redshift/latest/dg/r_patternmatching_condition_like.html) 運算子。`LIKE`運算子仍偏好 [SIMILAR TO](https://docs.aws.amazon.com/redshift/latest/dg/pattern-matching-conditions-similar-to.html) 或 [POSIX](https://docs.aws.amazon.com/redshift/latest/dg/pattern-matching-conditions-posix.html) 運算子。

## 在 GROUP BY 子句中使用排序索引鍵
<a name="group-by-clauses"></a>

在 `GROUP BY`子句中使用排序索引鍵，讓查詢規劃器可以使用更有效率的彙總。當查詢的`GROUP BY`清單僅包含排序索引鍵資料欄時，查詢可能符合單階段彙總的資格，其中一個也是分佈索引鍵。`GROUP BY` 清單中的排序索引鍵資料欄必須包含第一個排序索引鍵，後面接著您要依排序索引鍵順序使用的其他排序索引鍵。

## 利用具體化視觀表
<a name="materialized-views"></a>

如果可能，將複雜程式碼取代為具體化視觀表來重寫查詢，這將大幅改善查詢的效能。如需詳細資訊，請參閱[《Amazon Redshift 文件》中的在 Amazon Redshift 中建立具體化視](https://docs.aws.amazon.com/redshift/latest/dg/materialized-view-overview.html)觀表。

## 請注意 GROUP BY 和 ORDER BY 子句中的資料欄
<a name="group-by-order-by"></a>

如果您同時使用 `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
```