Tips8.チューニングの第一歩、SQL発行回数とインデックス

Oracle, PL/SQL, パフォーマンスOracle, SQL, パフォーマンス

データベースのパフォーマンス・チューニングというと、難しい印象があるのかもしれません。

「チューニングは難しいか」と問われると、正直一言では何とも答えられません。
簡単なチューニングもあれば、難しいチューニングもあります。
ただ、少し言い換えると、「最低限やっておくべきチューニング」もあれば、「実際に本番稼働してみなければわからないチューニング」もあります。

まず、チューニングを行うにあたって、いろいろ覚えたり考えたりする前に、最も基本的な大原則ことが一つあります。
それは、「チューニングとは、CPU・メモリ・ディスクという3つのコンピュータを構成するリソースを有効に利用すること」であるということです。
これがチューニングを行う上での大原則になりますので、必ず頭の根底部分に留めておいてください。

チューニングにおいては様々な手法が登場しますが、それらは全て上記の大原則を実現するためのものです。
例えば、SQLで全表走査を避けインデックスを使う、というRDBにおいて基本的なチューニング手法がありますが、
これはディスクへのアクセスを減らすことを目的とした手法の一つです。

「最低限やっておくべきチューニング」

まず最初に考えることは「極力SQLの数を減らすこと」です。
例えば、emp表、dept表から社員番号7900の、社員番号、社員名、組織名を取得する場合、

SELECT empno, ename, deptno FROM emp WHERE empno=7900;
SELECT dname FROM dept WHERE deptno=30;

と、SQLを2回発行するよりも、

SELECT e.empno, e.ename, e.deptno, d.dname
FROM   emp e INNER JOIN dept d
       ON e.deptno = d.deptno
WHERE  e.empno=7900;

と1回のSQLで取得すべきです。
それは何故でしょうか。

SQLの発行に際して、データベースは大きく3つのステップでSQLを実行します。
 1.SQLの構文解析を行い、
 2.実行計画を作成し、
 3.データの検索と取得を行います。

SQLを複数回発行すると、この一連の流れを複数回実行することになります。
一方、一つのSQLで複数の表を参照すると、構文解析からデータ検索までの処理が重たくなります。

軽量なSQL実行の一連の流れを複数回行うか、SQLを複雑にして流れの一部を重たくするかのトレードオフなのですが、大抵の場合はSQLを複雑にしてでも、SQLの発行回数を減らした方が、全体の処理時間は短くなります

それは、SQL発行のためのイニシャルコスト(SQLを実行するために最小限の使用リソース)よりも、解析や実行が速いということです。

言い方を変えれば、分割されたSQLを一つのSQLにまとめたらかえって遅くなったら、それはSQLの書き方に問題がある、ということです。
SQLの構成、抽出条件を見直すことから始めましょう。

もちろん、複雑な条件を持つSQLの場合は、分割し、中間テーブルを作成した方が良い場合もあります。

インデックスの作成の検討

設計初心者にありがちなケースとして、SQLが出来上がったら真っ先にチューニングのため、JOIN句やWHERE句の条件となっているカラムにINDEXを張るということをしがちですが、これはお勧めしません。

一意性を担保するプライマリキーやユニークインデックスは作成すべきですが、性能向上を目的としたインデックスは、その後の機能間の結合試験を経て検討します。

複数のSQLが一つの表を参照する場合に、どのようにインデックスを張っておくべきかは、システム全体からの視点を持って決定すべきです。

例えば、列A,Bを条件とする処理αと、列B,Cを条件とする処理βがあった場合に、A,BとB,Cのインデックスを2つ作るよりも、A,B,Cのインデックスを一つ作る方が効率が良いでしょう。
処理αだけを見ては、どのようなインデックスを張るべきかは判断できません。
登録・更新時の性能やインデックスのメンテナンスを考慮し、総合的に判断すべきです。