TimesTenは、コスト・ベースの問合せオプティマイザを備えています。これは、実現可能な問合せ計画を検討して、指定された問合せを実行するための最も効率的な方法を自動で判断することで、効率的なデータ・アクセスを保証します。最適化はコンパイル・プロセスの第3段階目で行われます。図5-1に、コンパイルの段階を示します。
複数の実行計画が可能な場合、TimesTenによってSQL文用のオプティマイザが起動されます。オプティマイザは、最適と判断した計画を選択します。この計画は、文がアプリケーションによって無効にされるか削除されるまで保持されます。
オプティマイザでは、次の情報に基づいて計画のコストを判断します。
表と列の統計情報
メタデータ情報(参照整合性、主キーなど)
索引の有無。索引の選択(一時索引の作成を含む。)
データの量
一意の値の数
条件の選択性
スキャン方法(全表スキャン、ROWID参照、範囲索引スキャン、ハッシュ索引参照)
結合アルゴリズムの選択(ネステッド・ループ結合、索引付きネステッド・ループ結合、マージ結合)
この章の内容は次のとおりです。
問合せオプティマイザの詳細は、『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』のTimesTenの問合せオプティマイザに関する説明を参照してください。
オプティマイザは、適切な時間とメモリー制約内で実現可能な最高の計画の生成を目的に設計されています。検索領域のサイズ(結合内の表の数とともに指数関数的に増加する)のため、オプティマイザは常にすべての問合せに最適な計画を選択できるわけではありません。オプティマイザの目的は、計画の検索領域内で最も有効な可能性が高い領域を検出する方法を使用して、生成された一連の計画から最適な計画を選択することです。問合せ最適化は実行に比較的時間がかかるため、オプティマイザは、最適化の時間よりも実行時間が優先されるように設計されています。
オプティマイザの生成する計画では、メモリーの使用よりパフォーマンスが重視されます。オプティマイザによって、実行を高速化するために、大量の一時メモリー空間を使用するように指示される可能性があります。メモリー制約のある環境では、「オプティマイザ・ヒント」で説明するオプティマイザ・ヒントをアプリケーションで使用して、一時索引と一時表の使用を禁止し、パフォーマンスを最大化せずにメモリーの使用を節約する計画を作成することもできます。
問合せの実行パスを判断する際に、オプティマイザは表の行数などの問合せで参照されるデータ、条件で使用される列の間隔の統計における最小値、最大値および一意の値の数、表内の主キーの有無および一意制約、既存の索引のサイズと構成などに関する統計を調べます。
表レベルと列レベルの統計は、SYS.TBL_STATS
表とSYS.COL_STATS
表に格納されます。これらの表は、アプリケーションでttOptUpdateStats
またはttOptEstimateStats
組込みプロシージャをコールするとき、またはttIsql
statsupdate
またはstatsestimate
コマンドを使用するときに移入されます。
オプティマイザでは、各表の統計を使用して、t1.a=4
のような条件、またはt1.a=4 AND t1.b<10
のような条件の組合せの選択性が計算されます。選択性とは、表に含まれる行数を測定したものです。割合の小さい行を選択する条件は選択性が高く、割合の大きい行を選択する条件は選択性が低いと言えます。
ヒントを適用して、TimesTen問合せオプティマイザに指示を渡すことができます。問合せに対して最適な実行計画を選択するとき、オプティマイザではこれらのヒントが考慮されます。次のようにヒントを適用できます。
特定のSQL文のみにヒントを適用するには、文レベルのオプティマイザ・ヒントを使用します。
トランザクション全体にヒントを適用するには、適切なTimesTen組込みプロシージャとともにトランザクション・レベルのオプティマイザ・ヒントを使用します。
ユーザー・アプリケーションのすべてのSQL文にヒントを適用するには、OptimizerHint
接続属性とともに接続レベルのオプティマイザ・ヒントを使用します。
オプティマイザ・ヒントの優先順位は、文レベルのヒント、トランザクション・レベルのヒント、接続レベルのヒントの順になります。
すべてオプティマイザ・ヒントの詳細は、Oracle TimesTen In-Memory Databaseオペレーション・ガイドのオプティマイザ・ヒントを使用した実行計画の変更を参照してください。
問合せオプティマイザは、索引を使用して問合せの実行を高速化します。オプティマイザは、既存の索引を使用するか、一時索引を作成して、実行計画を生成します。索引とは、表の行の位置を示すキーのマップです。TimesTenシステムから最大のパフォーマンスを引き出すには、索引を戦略的に使用することが必須になります。
TimesTenでは、次のタイプの索引を使用します。
TimesTenでは2種類の索引を使用し、それぞれを一意または一意でない(デフォルト)として定義できます。
ハッシュ索引: ハッシュ索引は、1つ以上の列で完全一致する行を検索する場合に有効です。ハッシュ索引は、CREATE HASH INDEX
SQL文を使用して作成します。通常、完全一致参照と等価結合については、ハッシュ索引の方が範囲索引より高速です。ただし、範囲またはキーの接頭辞を含む参照ではハッシュ索引を使用できません。また、ハッシュ索引では範囲索引より多くの領域が必要になる可能性があります。
範囲索引: 範囲索引は、列の値が等価または非等価として指定された範囲内にある行を検出する場合に有効です。範囲索引は、表の1つ以上の列にわたって作成できます。範囲索引は、CREATE INDEX
SQL文を使用して作成します。
索引の詳細は、『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』の索引の理解に関する説明を参照してください。『Oracle TimesTen In-Memory Database SQLリファレンス』のCREATE INDEX文の説明も参照してください。
索引アドバイザ・ツールを使用して、特定のSQLワークロードのパフォーマンスを向上できる一連の索引を推奨できます。詳細は、『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』の索引アドバイザを使用した索引の推奨に関する説明を参照してください。
オプティマイザは複数のタイプのスキャン方法から選択できます。最も一般的なスキャン方法は次のとおりです。
全表スキャン: 全表スキャンでは、表内のすべての行が調べられます。全体スキャンは通常、問合せ条件を評価する最も非効率的な方法であるため、他の方法を使用できない場合にのみ使用されます。
ROWID参照: ROWIDは、表に格納されている各行に対する表内の物理タプルのアドレス(一意のID)です。たとえば、アプリケーションで以前にROWIDを選択し、次にWHERE ROWID=
句を使用して同じ行をフェッチする場合に、ROWID参照が適用可能です。ROWID参照は索引参照より高速です。
ただし、TimesTen Scaleoutは複数のコピーを持つように構成できるため、各コピーには異なるROWID
が割り当てられます。ROWID
は行の特定のコピーの識別子であるため、そのコピーを使用できない場合は、ROWID
で行にアクセスできません。この場合は、主キーで行にアクセスする必要があります。
詳細は、『Oracle TimesTen In-Memory Database Scaleoutユーザーズ・ガイド』のデータ配分におけるROWIDの理解に関する項を参照してください。
(永続索引または一時索引のいずれかにおける)範囲索引スキャン: 範囲索引スキャンでは、表にアクセスするために範囲索引が使用されます。このようなスキャンは、条件に使用する列に範囲索引が定義されている場合にのみ、t1.a=2
などの完全一致条件またはt1.a>2
やt1.a<10
などの範囲条件に適用できます。範囲索引が複数の列にわたって定義されている場合は、複数の列条件にその範囲索引を使用できます。たとえば、列t1.b
およびt1.c
に範囲索引が定義されている場合、条件t1.b=100
およびt1.c>'ABC'
は範囲索引スキャンになります。索引は、複数の列にわたって定義されている場合でも使用できます。たとえば、t1.b
、t1.c
およびt1.d
に範囲索引が定義されている場合、オプティマイザでは、列b
およびc
の索引の接頭辞が使用され、列b
およびc
に指定した条件に一致する列d
のすべての値が返されます。
(永続索引または一時索引における)ハッシュ索引参照: ハッシュ索引参照は、ハッシュ索引を使用して、1つ以上の列で完全一致を使用して行を検索します。このような参照は、指定した1つ以上の列における等価検索に適用されます。
TimesTenでは、ハッシュ索引およびROWID参照を使用して高速に完全一致処理が実行されます。また、範囲索引を介して範囲一致処理が実行されます。問合せ計画の選択時にオプティマイザによる特定のスキャン方法についての検討を実行可能または実行不可にするには、オプティマイザ・ヒントを使用します。
オプティマイザは複数の結合方法のいずれかを選択できます。2つの表の行を結合する場合は、一方の表を外部表、他方の表を内部表に指定します。オプティマイザは、どちらの表を外部表にしてどちらを内部表にするかを決定します。結合中に、オプティマイザは外部表と内部表の行をスキャンして、結合条件に一致する行を検索します。
オプティマイザは各表の統計を分析します。たとえば、オプティマイザは、最小の表、または問合せについて最高の選択性を持つ表を外部表として識別します。結合する1つ以上の表に索引が存在する場合、オプティマイザでは外部表と内部表を選択する際にそれらを考慮します。
3つ以上の表を結合する場合、オプティマイザは表のペアについて様々な結合の組合せを分析し、最初に結合するペア、次にその結合の結果によって結合する表など、最適な結合の順序を判断します。
結合のコストは、内部表と外部表にアクセスして、結合条件に一致する行を検索する方法に大きく影響されます。オプティマイザは、問合せオプティマイザ計画を決定する際に2つの結合方法から選択します。
索引のないネステッド・ループ結合では、外部表の行が一度に1行ずつ選択され、内部表のすべての行と一致するか確認されます。内部表のすべての行が、外部表の行数と同じ回数スキャンされます。内部表の結合列に索引がある場合、その索引は結合条件を満たす行の選択に使用されます。各表から結合条件を満たす行が返されます。処理中に、索引がネステッド・ループの内部表に対して作成され、内部スキャンの結果が結合の前にマテリアライズされる可能性があります。
図5-2に、ネステッド・ループ結合の例を示します。結条件は次のとおりです。
WHERE t1.a=t2.a
この例では、オプティマイザはt1
が外部表、t2
が内部表と決定しています。表t2
内の列a
の値と一致している表t1
内の列a
の値は1および7です。結合の結果、t1
およびt2
の行が連結されます。たとえば、最初の結合結果は次の行になります。
7 50 43.54 21 13.69
次のt1
の行が連結されます。
7 50 43.54
列a
の値が一致しているt2
の最初の行を次に示します。
7 21 13.69
マージ結合は、結合列が範囲索引でソートされる場合にのみ使用されます。マージ結合では、カーソルが各索引を一度に1行ずつ進みます。行はすでに各索引の結合列でソートされているため、簡単な式を適用することにより、単一のスキャンでカーソルが各行を効率的に進みます。式は次のようになります。
内部.結合列 < 外部.結合列の場合、内部カーソルを進める
内部.結合列 = 外部.結合列の場合、一致を読み取る
内部.結合列 > 外部.結合列の場合、外部カーソルを進める
ネステッド・ループ結合と異なり、外部表の各行について内部表全体をスキャンする必要はありません。マージ結合が使用できるのは、問合せを準備する前に表に範囲索引が作成されている場合です。問合せを準備する前に、結合する表に範囲索引が存在しない場合、状況によっては、オプティマイザがマージ結合を使用するために、一時範囲索引を作成する可能性もあります。
図5-3に、マージ結合の例を示します。結条件は次のとおりです。
WHERE t1.a=t2.a
x1
は、表t1
の索引を列a
でソートしたものです。x2
は、表t2
の索引を列a
でソートしたものです。マージ結合の結果、x1
の行は、列a
の値が一致するx2
の行と連結されます。たとえば、最初のマージ結合の結果は次のようになります。たとえば、最初のマージ結合の結果は次のようになります。
1 20 23.09 20 43.59
次のx1
の行が連結されます。
1 20 23.09
列a
の値が一致しているx2
の最初の行を次に示します。
1 20 43.59
他の多くのリレーショナル・データベースのオプティマイザと同様に、問合せオプティマイザは最も効率的なSQL処理方法の詳細を問合せ実行計画に保存し、アプリケーション開発者と管理者は、これを確認してカスタマイズできます。
実行計画のデータは、TimesTenのSYS.PLAN
表に保存され、アクセスする表とその順序、結合する表、使用する索引に関する情報を含みます。ttSqlCmdQueryPlan
組込みプロシージャまたはttIsql
explain
コマンドのいずれかを使用して、最近実行されたSQL文の問合せ計画を表示できます。ユーザーは計画生成オプティマイザ・ヒントを使用して、SYS.PLAN
表での実行計画の作成を有効または無効にするように問合せオプティマイザに指示できます。(トランザクション・レベルのヒントの場合は、ttOptSetFlag
組込みプロシージャでGenPlan
オプティマイザ・フラグを使用し、文レベルのヒントの場合は、SQL文でTT_GenPlan
ヒントを使用します)。詳細は、Oracle TimesTen In-Memory Databaseオペレーション・ガイドのTimesTen問合せオプティマイザを参照してください。
実行計画は、実行するデータベース処理ごとに個別のステップを指定して、問合せを実行します。計画内のステップは複数のレベルに編成されます。レベルでは、次のレベルの1つ以上のステップで必要となる結果を生成するために完了する必要があるステップを指定します。
次の問合せについて考えてみます。
SELECT COUNT(*) FROM t1, t2, t3 WHERE t3.b/t1.b > 1 AND t2.b <> 0 AND t1.a = -t2.a AND t2.a = t3.a;
この例では、図5-4に示すように、オプティマイザは問合せを個別の操作に分解し、3つのレベルで実行される5つのステップを生成します。