データベースが複数の実行プランのコストを見積もり、最も効率的なプランを自動選択する仕組み
コストベース最適化(Cost-Based Optimization, CBO)は、PostgreSQL・MySQL・Oracleなど主要なRDBMSがデフォルトで採用しているクエリ最適化手法です。 SQLクエリを受け取ると、データベースはそれを実行する方法(実行プラン)を複数生成し、テーブル統計情報(行数・カーディナリティ・データ分布)を元に各プランのコストを数値化します。 そして最もコストが低い(=最も効率が良いと推定される)プランを自動的に選択して実行します。
開発者は EXPLAIN ANALYZE コマンドで、オプティマイザがどのプランを選んだか、実際のコストはいくつだったかを確認できます。 スロークエリの原因調査やインデックス設計の判断に不可欠なツールです。
コストの計算にはディスクI/Oコスト(ページ読み取り回数)とCPUコスト(行処理・比較演算)が含まれます。 PostgreSQLの場合、シーケンシャルページ読み取りのコストは seq_page_cost = 1.0、ランダムページ読み取りは random_page_cost = 4.0 がデフォルトです。
このビジュアライザは、PostgreSQLのコストモデルに準拠した計算式を使って、各実行プランの推定コストを算出しています。 コストの単位は「ディスクページ1回のシーケンシャル読み取りを 1.0 とした相対値」です。絶対的な実行時間ではなく、プラン同士の相対比較に使います。
コストベース最適化は、以下の4つのステップで実行されます。SQLを受け取ってから実行プランが決定するまで、通常は数ミリ秒以内に完了します。
レストランを選ぶとき、まず口コミサイトで評価や距離を調べますよね? データベースも同じで、テーブルの行数・値の分布・インデックスの有無などの「口コミ情報」を事前に収集しています。PostgreSQLでは ANALYZE コマンドがこの収集を行います。
目的地へのルートを複数調べるイメージです。「高速道路を使う」「下道を行く」「電車で行く」のように、同じクエリでも実行方法は何通りもあります。
各ルートの所要時間を見積もるイメージです。高速道路は速いけど料金がかかる(ランダムI/Oは速いがコスト4.0)、下道は遅いが無料(シーケンシャルI/Oはコスト1.0)。
見積もりが最も安いルートを選びます。これがEXPLAINで表示されるプランです。
CBOが登場する前は、Rule-Based Optimization(RBO)が主流でした。RBOは「インデックスがあれば必ず使う」「JOINは常にnested_loopで行う」といった固定ルールに従います。 現代のRDBMSではCBOが標準ですが、MySQL 5.x以前やOracle 7以前はRBOがデフォルトでした。
| 観点 | Cost-Based(CBO) | Rule-Based(RBO) |
|---|---|---|
| 判断基準 | 統計情報に基づくコスト計算 | 事前定義された優先順位ルール |
| データ量への適応 | 行数・分布に応じて最適プランが変化 | データ量に関係なく同じルールを適用 |
| インデックス利用 | 選択率に応じて使う/使わないを判断 | インデックスがあれば常に使用 |
| JOIN方式 | コスト比較でNL/Hash/Mergeを選択 | 固定(通常Nested Loopのみ) |
| 統計情報 | 必須(ANALYZE / autovacuum) | 不要 |
| 採用DB | PostgreSQL, MySQL 8+, Oracle 10g+ | Oracle 7以前, 古いMySQL |
| 精度 | 統計が正確なら高精度 | データ量が増えると非効率になりやすい |