

 Amazon Redshift は、パッチ 198 以降、新しい 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/)を参照してください。

# Amazon Redshift クエリの設計のベストプラクティス
<a name="c_designing-queries-best-practices"></a>

クエリパフォーマンスを最大化するには、クエリの作成時に次の推奨事項に従います。
+ ベストプラクティスに従ってテーブルを設計し、クエリパフォーマンスの強固な基盤を提供します。詳細については、「[Amazon Redshift テーブル設計のベストプラクティス](c_designing-tables-best-practices.md)」を参照してください。
+ `select *` は使用しないでください。明確に必要な列のみを含めます。
+ 同じテーブルから複数回選択するのではなく、[CASE 条件式](r_CASE_function.md) を使用して複雑な集計を実行します。
+ どうしても必要でなければクロス結合を使用しないでください。これらの結合に結合条件がないと、2 つのテーブルのデカルト積が求められます。クロス結合は通常ネステッドループ結合として実行されますが、これは使用可能な結合タイプで最も低速な結合です。
+ クエリのテーブル 1 つが述語条件のみで使用されている場合には、サブクエリを使用します。この場合、サブクエリはわずかな数の行を返します (ほぼ 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) 演算子が推奨されます。[SIMILAR TO](pattern-matching-conditions-similar-to.md) または [POSIX 演算子](pattern-matching-conditions-posix.md) には、引き続き LIKE 演算子が推奨されます。
+ クエリ述語で関数を使用しないでください。それらを使用すると、クエリの中間ステップの解決に多くの行が必要になるため、クエリのコストが上昇する可能性があります。
+ 可能な場合、データセットを制限するために、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;
  ```

  `sales.saletime` の述語が WHERE 句に含まれないため、実行エンジンは `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 リストにソートキー列のみが含まれており、そのうち 1 つが分散キーでもある場合、クエリは 1 フェーズ集計の対象となる可能性があります。GROUP BY リストのソートキー列には、1 番目のソートキーの後に、ソートキー順序で使用する他のソートキーが含まれている必要があります。例えば、1 番目のソートキーを使用する、1 番目と 2 番目のソートキーを使用する、1 番目、2 番目、3 番目のソートキーを使用する、などが有効です。1 番目と 3 番目のソートキーを使用することは有効ではありません。

  [EXPLAIN](r_EXPLAIN.md) コマンドを実行し、クエリの集計ステップで `XN GroupAggregate` を探すことにより、1 フェーズ集計の使用を確認できます。
+ GROUP BY 句と ORDER BY 句の両方を使用する場合、必ずどちらにも同じ順序で列を配置してください。つまり、次の方法を使用します。

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

  次の方法は使用しないでください。

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