3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SQLチューニングへのECRS原則の適用

Last updated at Posted at 2025-09-30

前置き

SQLの実行する前に、「どのようにプロセスが実行され、どのようを改善したら素早いクエリが実行できるのか?を図形的に捉えることは重要なことです。

策もなしに、SQLを雑に描いていては、素早く実行できるものも、遅くなってしまいます。

そこで今回は、ECRS原則を用いた、SQLチューニングについて触れていきます。

ECRSについて簡単におさらい

この原則については、過去にいろいろ記事を書いてるのでそちらを参考にしてください。

ECRS原則は、もともと製造業の業務改善(カイゼン)で使われる考え方ですが、SQLのクエリチューニングに応用するのは、非常に的確で効果的なアプローチです。

JOIN句は、テーブルのデータを一度メモリ上に展開し、結合条件に基づいてレコードを照合するという、本質的にコストの高い操作です。
そのため、ボトルネックに割かしなりやすい部分ではあります。

ECRSのフレームワークは、このコストの高いJOIN操作を、体系的に見直すための優れた思考ツールとなります。

Eliminate (なくせないか? - 排除)

「そもそも、このJOINは本当に必要か?」

を問います。JOIN句自体をなくせれば、効果は絶大です。

非正規化

最も強力な手法です。

ordersテーブルを検索する際に、顧客名を表示するために毎回customersテーブルをJOINしているのであれば、あらかじめordersテーブルにcustomer_nameカラムを追加・保存しておくことで、JOINそのものを排除します。

ただし、データの冗長性とのトレードオフになる。

これにより、読み取り時のJOINは不要になりますが、代わりに書き込み(INSERT/UPDATE)時に、以下のように両方のデータを同期させる余分な処理が必要になります。

image.png

データの不整合リスクが上がるので、私はほぼこの手法は好みません。

不要なJOINの削除

クエリをコピー&ペーストするうちに、SELECT句では使われていないのに、JOIN句だけが残っているケースがあります。
このような不要なJOINは、単純に削除します。

Combine (一緒にできないか? - 結合)

「複数の処理を、より少ない処理にまとめられないか?」

を問います。

クエリの統合

アプリケーションが、ループ内で何度も個別のクエリを発行しているのであれば、それらをUNION ALLやCASE文を使って、単一のクエリにまとめることで、データベースへのラウンドトリップ(往復回数)を減らします。

マテリアライズド・ビュー(実体化ビュー)

頻繁にJOINされるテーブル群を、あらかじめJOINした結果として、物理的なテーブル(マテリアライズド・ビュー)として保持しておきます。
クエリは、この事前に結合済みの単一テーブルを参照するだけで済みます。

詳細

特に分析系のクエリで、毎回同じ複雑なJOINや集計を繰り返している場合に有効です。
その重いクエリの結果を、あらかじめ物理的な実体を持つマテリアライズド・ビューとして保存しておく。
すると利用者は、その軽量な結果テーブルを叩くだけで済むようになります。

※トレードオフは、データの鮮度です。

ビューは定期的にリフレッシュする必要があり、リアルタイムのデータは反映されません。

具体例

日次の売上集計レポートのために、毎回重い集計クエリを実行している場合。

スクリーンショット 2025-10-01 080743.png

Rearrange (順序を変えられないか? - 交換)

「処理の順序を入れ替えて、効率化できないか?」

を問います。

先にフィルタ、後でJOIN

巨大なテーブル同士をJOINする前に、WHERE句やサブクエリ、CTE(共通テーブル式) を使って、各テーブルをできるだけ小さなサイズに絞り込んでからJOINします。

これにより、JOINが処理すべきレコード数が劇的に減り、パフォーマンスが向上します。

詳細

巨大なテーブル同士をJOINする場合、

JOINする前にWHERE句で可能な限りレコードを絞り込む

ことが鉄則です。
これにより、JOINアルゴリズムが処理しなければならないデータ量が劇的に減ります。

現代の多くのクエリオプティマイザは自動でこれを行いますが、サブクエリやCTE(共通テーブル式)を使って明示的に順序を指示することで、より確実な性能向上が期待できます。

具体例

東京都の顧客の注文履歴を検索する場合。

image.png

Simplify (もっと単純にできないか? - 単純化)

「処理をもっとシンプルな方法で実現できないか?」

を問います。

上記のEやCが実行できそうにない時には、ココから始めてしまっても何ら問題ないです。

インデックスの活用

JOINするカラムや、WHERE句で頻繁に使うカラムに適切なインデックスを作成します。
これにより、テーブルのフルスキャンという最も重い処理が、高速なインデックス検索に置き換わります。

WHERE句の関数使用を避ける

WHERE YEAR(order_date) = 2025

のような書き方は、order_dateのインデックスが使えなくなる原因です。

WHERE order_date >= '2025-01-01' AND order_date < '2026-01-01'

のように、インデックスが有効になるシンプルな比較に書き換えます。

具体例

顧客コードの先頭2文字が'TK'の顧客を探すような場合。

スクリーンショット 2025-10-01 081842.png

存在確認にはEXISTSを使う

「テーブルAに存在するレコードのうち、テーブルBにも対応するレコードが存在するもの」を取得したい場合、JOINやIN句よりもWHERE EXISTS (...)を使った方が、高速になることがあります。

まとめ

このように、ECRSの原則を適用することで、場当たり的ではない、体系的なクエリの改善・リファクタリングが可能になります。

是非、いきなりSQL書くんでなく、一旦立ち止まり、モデルを描いて、ECRSを適用してみてから、コードを書いてみてください。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?