【データベース】実行計画の要!「オプティマイザー」の役割と2つのアプローチ
リレーショナルデータベース(RDB)に対してSQL文を発行する際、私たちは「どのようなデータを満たすか(WHAT)」だけを指定し、「どのようにデータを取得するか(HOW)」の手順は記述しない。
この「どのようにデータを取得するか」という具体的なアクセス経路(実行計画)を裏で自動的に導き出しているのが、DBMSの心臓部である「オプティマイザー(最適化エンジン)」である。
1. オプティマイザーとは
データベースアクセスを最適化する仕組み、およびそのシステムをオプティマイザーと呼ぶ。
オプティマイザーは、ユーザーから送られてきたSQL文を構文解析(パース)し、テーブルの構造やインデックスの有無を分析する。その後、内部で複数の実行計画(プラン)を組み立て、その中から最も効率が良いと判断したアクセス経路を検出して実行に移す役割を担っている。
2. オプティマイザーの2つの種類
SQL文の実行計画を選択・決定する手法には、歴史的な経緯やアプローチの違いにより、大きく分けて次の2種類が存在する。
(1)ルールベース・オプティマイザー(RBO)
ルールベースのオプティマイザーは、データの量や状態に関わらず、あらかじめシステムに組み込まれた固定の優先順位(ルール)に則って、機械的に実行計画を決定する。
一般的には、以下のようなアクセス・パス(経路)の優先順位が定義されており、より上位の条件にマッチするインデックス等があれば、それを優先的に選択する。
- (ア)ユニーク・キーまたは主キーによる単一行アクセス(最優先)
- (イ)インデックス付きのクラスター・キー
- (ウ)複合インデックス(複数カラムを組み合わせたインデックス)
- (エ)単一カラム・インデックス
- (オ)ソート/マージ結合
- (カ)インデックス付きカラムの
MAXまたはMIN関数 - (キ)インデックス付きカラムの
ORDER BY - (ク)テーブル全体のスキャン(フルスキャン)(最も優先順位が低い)
(2)コストベース・オプティマイザー(CBO)
現在の主要なDBMS(Oracle、PostgreSQL、MySQL、SQL Serverなど)で主流となっているのが、このコストベースである。
あらかじめデータベース内に収集・蓄積されている、テーブルのレコード数、カラムの平均長、インデックスの深さ、データの分布度といった「統計情報」を基にする。
オプティマイザーは内部で複数の実行計画をシミュレーションし、それぞれのパターンで発生する「コスト」を計算して、最もコストが低いプランを採用する。
※ここでいう「コスト」とは、SQL文を実行するために必要と予測される、CPU処理時間やディスクI/O(読み書き)の経過時間に比例する見積値のことである。データ量が少なければフルスキャンを選び、データ量が多ければインデックスを選ぶ、といった柔軟な判断が可能となる。
3. まとめ
ルールベースは「構造」だけで判断するためデータ量の変化に弱く、現代の複雑なシステムでは不都合が生じやすい。そのため、現在のRDB運用においては、定期的に ANALYZE などのコマンドを実行して最新の「統計情報」を維持し、コストベース・オプティマイザーに正しい判断をさせることが、パフォーマンス管理における最大の鉄則となっている。
□ 意図しないフルスキャン(テーブル全体スキャン)が発生していないか?
□ 大規模なデータ更新(バッチ処理等)のあとに統計情報を更新しているか?
□ 期待通りのインデックスアクセスが選択されるよう、実行計画(EXPLAIN)を確認したか?