Tocyukiのブログ

ギターと柔術とプログラミングが好き!

SQLパフォーマンス改善手法について

mattnさんがめちゃくちゃ良い感じの回答をしてくれていたが、詳細については触れていなかったのでほんの少しだけ回答を深掘ってみる。

mond.how

以下、引用

SQL でパフォーマンス改善するには幾らか手法がありますが、おおよそは以下の数個に絞られます。

  • フルスキャンを避ける事
  • インデックスを適切に張る事
  • 集約関数や分析関数の利用
  • 速い演算子や副問合せへの書き換え

なぜ速い演算子に書き換えるべきなのか、なぜ分析関数が必要のか、なぜフルスキャンを避けるべきなのか、なぜインデックスを張るとパフォーマンスが改善するのか、そして適切にインデックスを貼らないどうなるのか、といった内容は読み物として調べ、実際に試されるのが良いと思います。

一例を上げますとインデックスは張るだけで表引きについてはすぐにパフォーマンスが改善できるのですが、それはつまりデータ挿入時にインデックスを登録する事になるので、INSERT が遅くなったりデータ容量が増えたりします。

その辺りを経験して知見として持ちつつ要件にマッチするよううまく改善できるかがデータベースエンジニアとしての成長になると思います。残念ながら僕はウェブのサービスでこれらを体系的に学べる物を知りません(あるかもしれません)が、チュートリアルサイトは幾らかある様に思います。インデックスやフルスキャンといったキーワードを使って検索頂き、チュートリアルサイトを確認頂くのが良いと思います。

なぜフルスキャンを避けるべきなのか

フルスキャンとは

フルスキャン(テーブルスキャン)とは、データベースがテーブル内のすべての行を順番に読み込んで、条件に一致するデータを探す操作です。

なぜ避けるべきか

  • パフォーマンスの低下: テーブルが大きい場合、フルスキャンは非常に時間がかかります。
    • 大量のデータを読み込むため、I/O操作が増え、処理時間が長くなります。
  • リソースの消費: フルスキャンは、CPUやメモリ、ディスクI/Oを大量に消費します。
    • これにより、他のクエリやトランザクションが遅くなる可能性があります。

対策

  • インデックスの利用: インデックスを使うことで、データの検索を効率化できます。
    • インデックスは、特定の列に対して高速な検索を可能にするデータ構造です。
  • 適切なフィルタリング: クエリで必要なデータだけを取得するようにし、不要なデータのスキャンを避けます。

なぜインデックスを張るとパフォーマンスが改善するのか

インデックスとは

  • インデックスは、データベーステーブル内の特定の列に対して作成されるデータ構造で、検索を迅速にするための手法です。
  • B-treeやハッシュなどの構造が一般的です。

なぜパフォーマンスが改善するのか

  • 検索の高速化: インデックスを使用すると、特定の列に対して高速な検索が可能になります。
    • インデックスは、テーブル内のすべての行を読み込むのではなく、インデックス構造を参照するだけで済むため、検索が大幅に高速化します。
  • クエリの最適化: インデックスを使うことで、データベースのクエリオプティマイザが効率的なクエリプランを選択できるようになります。

適切にインデックスを貼らないとどうなるか

  • パフォーマンスの低下: インデックスがないと、フルスキャンが必要になるため、クエリのパフォーマンスが低下します。
  • クエリの複雑化: 適切なインデックスがないと、データの検索や結合が効率的に行えず、クエリが複雑になり、実行速度が遅くなります。

なぜ速い演算子に書き換えるべきなのか

速い演算子

演算子の選択は、クエリのパフォーマンスに大きな影響を与えます。

例えば、= 演算子は比較演算子の中で最も効率的ですが、LIKE 演算子はパターンマッチングのため、場合によってはパフォーマンスが低下することがあります。

副問合せ(サブクエリ)

副問合せは、主クエリ内で別のクエリを実行する手法です。

ただし、非効率なサブクエリは、パフォーマンスの低下を招く可能性があります。

なぜ書き換えが必要なのか

  • 効率的な演算子の使用: 適切な演算子を使用することで、クエリの実行速度が向上します。
    • 例えば、IN 演算子よりも EXISTS を使うことで、パフォーマンスが向上する場合があります。
  • サブクエリの最適化: サブクエリを使う場合は、クエリプランによってパフォーマンスが大きく変わります。
    • 必要な場合には、JOIN句に書き換えたり、サブクエリの結果を一時テーブルに保存してから利用することで、パフォーマンスを改善できます。

なぜ集約関数や分析関数が必要のか

集約関数とは

集約関数は、複数の行から1つの値を計算する関数です。

例として、SUM(), AVG(), COUNT() などがあります。

分析関数とは

分析関数(ウィンドウ関数)は、特定のウィンドウ(行のサブセット)に対して集計を行う関数です。

例として、ROW_NUMBER(), RANK(), LEAD(), LAG() などがあります。

なぜ必要なのか

  • 効率的なデータ処理: 集約関数を使うことで、大量のデータを効率的に処理し、必要な統計情報や集計結果を迅速に取得できます。
  • 複雑な計算の簡素化: 分析関数を使用することで、複雑な計算やデータ分析をSQLクエリ内で簡潔に表現できます。
    • これにより、アプリケーションコードの複雑さを減少させ、パフォーマンスを改善できます。

まとめ

  • フルスキャンを避ける: 大量のデータを無駄にスキャンせず、効率的な検索を実現します。
  • インデックスを適切に張る: データの検索を高速化し、クエリのパフォーマンスを向上させます。
  • 集約関数や分析関数の利用: 大量のデータから効率的に情報を取得し、複雑な計算を簡素化します。
  • 速い演算子や副問合せへの書き換え: クエリの効率を高め、パフォーマンスを最適化します。

これらの手法を理解し、適切に実施することで、SQLクエリのパフォーマンスを大幅に改善することができます。

このあたりの過去記事も参考になるかも

blog.tocyuki.com

blog.tocyuki.com