主コンテンツへ
Oracle® TimesTen In-Memory Databaseオペレーション・ガイド
リリース18.1
E98635-05
  目次へ移動
目次
索引へ移動
Index

前
 
次
 

9 TimesTen問合せオプティマイザ

TimesTen問合せオプティマイザはコストベースのオプティマイザで、使用可能な問合せ計画を検討することにより、指定された問合せを実行する最も効率的な方法を決定します。問合せオプティマイザでは、アプリケーションの表の情報と使用可能な索引を使用して、データへのファスト・パスを選択します。

TimesTen Scaleoutの問合せ計画は、ハッシュ分散スキームの分散スキームおよび分散キー、列および表の統計、索引の有無、データ量、一意の値の数、述語の選択性の影響を受けます。

アプリケーション開発者は、オプティマイザが選択したプランを確認して、索引が適切に使用されているかをチェックできます。またアプリケーション開発者は、必要に応じて、オプティマイザが別のプランを検討するように、オプティマイザの動作に影響を与えるヒントを提供できます。

この章の内容は次のとおりです。

最適化を実行するタイミング

複数の実行計画が可能な場合、TimesTenによってSQL文用のオプティマイザが起動されます。オプティマイザは、最適と判断した計画を選択します。この計画は、文がアプリケーションによって無効にされるか削除されるまで保持されます。

文は次の状況で自動的に無効化されます。

  • コマンドが使用するオブジェクトが破棄された

  • コマンドが使用するオブジェクトが変更された

  • コマンドが参照する表またはビューの索引が破棄された

  • コマンドが参照する表またはビューに索引が作成された

次のいずれかの方法を使用して、文を手動で無効化できます。

  • ttOptCmdCacheInvalidate組込みプロシージャを使用してSQLコマンド・キャッシュ内の文を無効化します。詳細は、「コマンドの無効化をSQLコマンド・キャッシュで制御する」を参照してください。

  • ttOptUpdateStatsまたはttOptEstimateStats組込みプロシージャで、invalidationオプションを1に設定します。これらの組込みプロシージャによって、指定した表または現在のユーザーが所有するすべての表の統計も更新されます。


ノート:

統計を計算するときの詳細は、「正確な統計または推定統計の計算」を参照してください。また、『Oracle TimesTen In-Memory Databaseリファレンス』のttOptUpdateStatsに関する項またはttOptEstimateStatsに関する項も参照してください。

無効になった文は、通常、再実行される直前に再度自動的に準備されます。つまり、その時点でオプティマイザが再度起動され、場合によっては新しい計画が作成されます。したがって、1つのコマンドが何度も準備されることがあります。


ノート:

JDBCを使用しているときは、表が変更された場合に、文を手動で再度準備する必要があります。

たとえば、文で参照していた表が破棄され、同じ名前の表が作成されたときには、文を手動で準備することが必要な場合があります。文を手動で準備する場合は、準備文を、共有できるようにコミットする必要があります。文が、無効なため再コンパイルされる場合、および参照されているいずれかの表で使用されているDDLが再コンパイルに必要な場合は、準備文をコミットしてコマンド・ロックを解放する必要があります。

たとえば、ODBCでは、表T1T2を結合するコマンドによって、次のような処理が行われます。

アクション 説明
SQLPrepare コマンドが準備されます。
SQLExecute コマンドが実行されます。
SQLExecute コマンドが再実行されます。
T1に対する索引の作成 コマンドが無効化されます。
SQLExecute コマンドが再度準備され、実行されます。
SQLExecute コマンドが再実行されます。
T1に対するttOptUpdateStats コマンドが無効になります(無効フラグがttOptUpdateStatsプロシージャに渡された場合)。
SQLExecute コマンドが再度準備され、実行されます。
SQLExecute コマンドが再実行されます。
SQLTransact コマンドがコミットされます。
SQLFreeStmt コマンドが破棄されます。

JDBCでは、表T1T2を結合するコマンドによって、次のような処理が行われます。

アクション 説明
Connection.prepareStatement() コマンドが準備されます。
PreparedStatement.execute() コマンドが実行されます。
PreparedStatement.execute() コマンドが再実行されます。
T1に対する索引の作成 コマンドが無効化されます。
PreparedStatement.execute() コマンドが再度準備され、実行されます。
PreparedStatement.execute() コマンドが再実行されます。
T1に対するttOptUpdateStats コマンドが無効になります(無効フラグがttOptUpdateStatsプロシージャに渡された場合)。
PreparedStatement.execute() コマンドが再度準備され、実行されます。
PreparedStatement.execute() コマンドが再実行されます。
Connection.commit() コマンドがコミットされます。
PreparedStatement.close() コマンドが破棄されます。

前述のとおり、最適化は、通常は準備のときに実行されますが、後で索引が破棄または作成されるときや、統計が変更されるときにも実行されることがあります。キャッシュ内のコマンドを準備で使用できる場合は、最適化は行われません。

コマンドの準備時にgenPlanフラグが設定されていた場合は、同じフラグが設定されて再度コンパイルされます。したがって、別の問合せのための計画がSYS.PLAN表内にある場合でも、計画は作成されます。

オプティマイザの動作をに影響を与えるオプティマイザ・ヒントをアプリケーションで指定した場合、これらのヒントはコマンドを削除するまで維持されます。詳細は、「計画生成の変更」を参照してください。たとえば、同じハンドルでODBC SQLPrepare関数またはJDBC Connection.prepareStatement()メソッドが再度コールされた場合や、SQLFreeStmt関数またはPreparedStatement.close()メソッドがコールされた場合などです。つまり、無効化が原因となって発生するすべての中間の再準備で、同じヒントが使用されることになります。

SQLコマンド・キャッシュに格納されているSQL文の表示

SQL文、組込みプロシージャなど、実行されたすべてのコマンドは、一時メモリーを使用するSQLコマンド・キャッシュに格納されます。コマンドはSQLコマンド・キャッシュの制限に達するまで格納され、その後は最後に使用されたコマンドが削除された後に新しいコマンドが格納されます。SQLコマンド・キャッシュに格納されているこれらのコマンドを1つ以上取得できます。


ノート:

この項では、SQLコマンド・キャッシュに格納されたコマンドの表示方法について説明します。これらのコマンドに関連付けられた問合せ計画の表示方法については、「SQLコマンド・キャッシュに格納されているコマンドに関連付けられた問合せ計画の表示」を参照してください。

次の項では、SQLコマンド・キャッシュに格納されているコマンドを表示する方法について説明します。

パフォーマンス管理およびトラブルシューティングのコマンド

1つ以上のコマンドまたはその問合せ計画の詳細は、ttSQLCmdCacheInfoおよびttSQLCmdQueryPlan組込みプロシージャで表示できます。問合せ計画情報は、問合せの監視およびトラブルシューティングに使用します。

コマンドおよび問合せ計画を表示すると、次の作業に役立ちます。

  • 索引スキャンを使用していない更新または削除の検出。

  • すべての計画を確実に最適化することを目的とする、実行中の問合せの問合せ計画の監視。

  • SQL文を準備しないアプリケーション、または同じ文を複数回再準備するアプリケーションの検出。

  • コマンド・キャッシュ内でパフォーマンスの評価に使用されている領域の割合の検出。

SQLコマンド・キャッシュに格納されたコマンドの表示

TimesTenデータベースに対して実行されたコマンドは、SQLコマンド・キャッシュにキャッシュされます。ttSQLCmdCacheInfo組込みプロシージャを使用すると、TimesTen SQLコマンド・キャッシュにキャッシュされた特定のコマンドまたはすべてのコマンドが表示されます。デフォルトではすべてのコマンドが表示されますが、コマンドIDを指定すると、そのコマンドのみが取得されて表示されます。

コマンド・データは、次の形式で保存されます。

  • コマンドID。特定のコマンドまたはそのコマンドに関連付けられた問合せ計画を取得する場合に使用されます。

  • プライベート接続ID。

  • 実行回数のカウンタ。

  • ユーザーがこの文を準備した回数のカウンタ。

  • ユーザーがこのSQL文を再準備した回数のカウンタ。

  • 解放可能かどうかのステータスで、この値が1の場合、サブデーモンはガベージ・コレクタで領域を解放できます。値が0の場合、領域は解放可能ではありません。

  • キャッシュ内でこのコマンドに対して割り当てられている合計サイズ(バイト)。

  • コマンドを作成したユーザー。

  • 最大1024文字の問合せテキスト。

  • この文のために内部的に行われたフェッチの実行回数です。

  • 文が開始したときのタイムスタンプです。

  • 最大実行時間が秒単位で表示されます。

  • 最後に測定された実行時間が秒単位で表示されます。

  • 最小実行時間が秒単位で表示されます。

  • TimesTenでコンパイルされた文の一意の識別子。

  • 最後に実行されたこのTimesTen文で使用された合計一時サイズ(バイト単位)。

  • このTimesTen文の実行にこれまで使用された最大一時サイズ(バイト単位)。

すべてのコマンドのリストの末尾には、キャッシュ内に格納されていたコマンド数を示すステータスが出力されます。

次の例は、ttSQLCmdCacheInfo組込みユーティリティを使用して、SQLコマンド・キャッシュにあるすべてまたは単一のコマンドを表示する方法を示しています。

例9-1 SQLコマンド・キャッシュ内のすべてのコマンドの表示

この例では、ttIsql内で引数を指定しないでttSQLCmdCacheInfo組込みプロシージャを実行し、キャッシュされたすべてのコマンドを表示します。コマンドは、簡潔な形式で表示されます。各列に列名が付加された情報を表示するには、ttSQLCmdCacheInfoプロシージャをコールする前にvertical onを実行してください。

Command> vertical 1;
Command> call ttSQLCmdCacheInfo;

  SQLCMDID:                        43402480
  PRIVATE_COMMAND_CONNECTION_ID:   -1
  EXECUTIONS:                      1
  PREPARES:                        1
  REPREPARES:                      0
  FREEABLE:                        1
  SIZE:                            4344
  OWNER:                           HR
  QUERYTEXT:                       INSERT INTO employees VALUES
        ( 191
        , 'Randall'
        , 'Perkins'
        , 'RPERKINS'
        , '650.505.4876'
        , TO_DATE('19-DEC-1999', 'dd-MON-yyyy')
        , 'SH_CLERK'
        , 2500
        , NULL
        , 122
        , 50
        )
  FETCHCOUNT:                      0
  STARTTIME:                       2015-04-09 15:22:22.139000
  MAXEXECUTETIME:                  0
  LASTEXECUTETIME:                 0
  MINEXECUTETIME:                  0
  GRIDCMDID:                       <NULL>
  TEMPSPACEUSAGE:                  0
  MAXTEMPSPACEUSAGE:               0
 
 
  SQLCMDID:                        43311000
  PRIVATE_COMMAND_CONNECTION_ID:   -1
  EXECUTIONS:                      1
  PREPARES:                        1
  REPREPARES:                      0
  FREEABLE:                        1
  SIZE:                            4328
  OWNER:                           HR
  QUERYTEXT:                       INSERT INTO employees VALUES
        ( 171
        , 'William'
        , 'Smith'
        , 'WSMITH'
        , '011.44.1343.629268'
        , TO_DATE('23-FEB-1999', 'dd-MON-yyyy')
        , 'SA_REP'
        , 7400
        , .15
        , 148
        , 80
        )
  FETCHCOUNT:                      0
  STARTTIME:                       2015-04-09 15:22:22.139000
  MAXEXECUTETIME:                  0
  LASTEXECUTETIME:                 0
  MINEXECUTETIME:                  0
  GRIDCMDID:                       <NULL>
  TEMPSPACEUSAGE:                  0
  MAXTEMPSPACEUSAGE:               0
 
 ...
102 rows found.

例9-2 単一のSQLコマンドの表示

ttSQLCmdCacheInfoに入力としてコマンドIDを指定すると、SQLコマンド・キャッシュから単一のコマンドが表示されます。ttSQLCmdCacheInfo組込みプロシージャにコマンドIDを入力しなかった場合、現在のすべてのコマンドに関する情報が表示されます。このとき、コマンドIDが出力の最初の列に表示されます。

次の例は、コマンドID 527973892で識別されるコマンドを表示します。これは、簡潔な形式で表示されます(先頭に列見出しを表示するには、組込みのttSQLCmdCacheInfoをコールする前にvertical onを実行してください)。

Command> call ttSQLCmdCacheInfo(43311000);
< 43311000, -1, 1, 1, 0, 1, 4328, HR, INSERT INTO employees VALUES
( 171, 'William', 'Smith', 'WSMITH', '011.44.1343.629268', TO_DATE('23-FEB-1999',
 'dd-MON-yyyy'), 'SA_REP', 7400, .15, 148, 80), 0, 2015-04-09 15:22:22.139000, 0,
 0, 0, <NULL>, 0, 0 > 
1 row found.

SQL問合せ計画の表示

コマンドの問合せ計画を表示するには、最新の問合せ計画をシステムPLAN表に格納する方法か、またはSQLコマンド・キャッシュにキャッシュされたすべてのコマンドとその問合せ計画を表示する方法のいずれかを使用します。次の項では、この2つの方法について説明します。

システムPLAN表からの問合せ計画の表示

オプティマイザによって、問合せ計画が準備されます。実行する最後のSQL文について、計画がシステムのPLAN表に格納されるように指示することができます。

  1. 計画を生成してシステムPLAN表に格納するようにTimesTenに指示します。

  2. 文の準備で、その文に対してODBC SQLPrepare関数またはJDBC Connection.prepareStatement()メソッドをコールします。PLAN表に計画が格納されます。

  3. SYS.PLAN表に生成された計画を読み取ります。

格納された計画は、コマンドの再準備が実行されるたびに自動的に更新されます。再準備は、次の1つ以上の状況が発生すると自動的に実行されます。

  • 文内の表が変更された場合。

  • 索引が作成または廃棄された場合。

  • アプリケーションで、統計の更新時に、ttOptUpdateStats組込みプロシージャのinvalidateオプションを使用してコマンドが無効化された場合。

  • ユーザーがttOptCmdCacheInvalidate組込みプロシージャを使用してコマンドを無効にした場合。


ノート:

詳細は、「コマンドの無効化をSQLコマンド・キャッシュで制御する」を参照してください。組込みプロシージャの詳細は、『Oracle TimesTen In-Memory Databaseリファレンス』のttOptUpdateStatsおよびttOptCmdCacheInvalidateに関する説明を参照してください。

このような場合は、計画がどのように変更されたかをPLAN表で確認します。

計画をシステムPLAN表に格納するようにTimesTenに指示する方法

システムのPLAN表で計画を表示する前に、計画生成オプションを次のように設定して、PLAN表内でのエントリの作成を有効にします。

  • トランザクション・レベルのオプティマイザのヒントについては、ttOptSetFlag組込みプロシージャを呼び出してGenPlanフラグを有効にします。

  • 文レベルのオプティマイザのヒントについては、TT_GENPLAN(1)を設定します。これはこの文でのみ有効です。文が実行された後、計画生成オプションによって、トランザクション・レベルのオプティマイザ・ヒントGenPlanの値が受け入れられます。


ノート:

文レベルとトランザクション・レベルのオプティマイザ・ヒントの詳細については、「オプティマイザ・ヒントを使用して実行計画を変更する」を参照してください。

これによって、それ以降にODBC SQLPrepare関数またはJDBC Connection.prepareStatement()メソッドのコールがトランザクションにあれば、そのすべてのコールから得られた計画が現在のSYS.PLAN表に保存されるようになります。

SYS.PLAN表に格納できる計画は1つのみです。このため、ODBC SQLPrepare関数またはJDBC Connection.prepareStatement()メソッドがコールされるたびに、その時点で表に格納されていた計画は上書きされます。

コマンドの準備時に計画生成オプションが設定されていた場合は、コマンドは計画生成時にも再度コンパイルされます。したがって、別の問合せのための計画がSYS.PLAN表内にある場合でも、計画は作成されます。

ttIsqlshowplanを使用して問合せおよびオプティマイザのヒントをテストできます。これにより計画生成が可能になるとともに、トランザクション内にある問合せ計画も示します。自動コミット・モードを無効にする必要があります。

Command> autocommit 0;
Command> showplan 1;

PLAN表からの問合せ計画の読取り

計画の生成を有効にしてコマンドの準備が終了すると、SYS.PLAN表の1つ以上の行にコマンドの計画が格納されます。表の行数は、コマンドがどの程度複雑かによって変わります。各行には、『Oracle TimesTen In-Memory Databaseシステム表およびビュー・リファレンス』のシステム表およびビューに関する項で説明されているとおり、列が7つあります。

例9-3 問合せ計画の生成

この例では、次の問合せを使用します。

Command> 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つのSYS.PLAN行が生成されます。各行は、計画の1つのステップで、問合せの実行時に実行される処理を示します。

ステップ レベル 処理 表名 索引名 条件 その他の条件
1 3 TblLkRangeScan t1 IX1 該当なし 該当なし
2 3 TblLkRangeScan t2 IX2(D) 該当なし t2.b <> 0
3 2 MergeJoin 該当なし 該当なし t1.a = -t2.a 該当なし
4 2 TblLkRangeScan t3 IX3(D) 該当なし 該当なし
5 1 MergeJoin 該当なし 該当なし t2.a = t3.a t3.b / t1.b > 1

SYS.PLAN表の各列の詳細は、「PLAN表の各列の説明」を参照してください。

PLAN表の各列の説明

SYS.PLAN表には、7つの列があります。

列1(ステップ)

処理の順序を示します(常に1から開始)。例9-3は、次の順序で表ロック範囲スキャンを使用します。

  1. t1のIX1で、表ロック範囲スキャンを実行します。

  2. t2のIX2で、表ロック範囲スキャンを実行します。

  3. t1t2などでマージ結合を実行します。

列2(レベル)

処理を表す結合ツリー図での操作の位置を示します。例9-3の結合ツリーは、次のとおりです。

jointree.pngの説明が続きます
図jointree.pngの説明

列3(処理)

実行される処理のタイプを示します。このフィールドで使用される可能性がある値とそれぞれが表す表スキャンのタイプの詳細は、『Oracle TimesTen In-Memory Databaseシステム表およびビュー・リファレンス』のシステム表およびビューに関する項で、SYS.PLANを参照してください。

オプティマイザが実行した処理内容がすべてユーザーに表示されるわけではありません。パフォーマンスの解析にとって重要な処理のみがSYS.PLAN表に表示されます。TblLkは、シリアライズ可能分離モードまたはコミット読取り分離モードでの実行時に使用可能なオプティマイザ・ヒントです。表ロックは、準備時に行ロックが無効になっている場合にのみスキャン時に使用されます。

列4(表名)

スキャンされる表を示します。この列は、実行される処理がスキャンの場合にのみ使用されます。それ以外の場合、この列はNULLです。

列5(索引名)

使用される索引を示します。この列は、処理が、既存の索引(ハッシュまたは範囲スキャン)を使用する索引スキャンの場合にのみ使用されます。それ以外の場合、この列はNULLです。スキャンが降順(小から大ではなく、大から小)の場合、範囲索引の名前に「(D)」が付きます。

列6(条件)

処理に条件が含まれる場合に、その条件を示します。条件が使用されるのは、索引スキャンとMergeJoinの処理のみです。条件文字列は、1,024文字に制限されています。

範囲スキャンの場合、この列は条件がないことを表すNULLになる場合があります。範囲スキャンに、フィルタリングの他に次のような2つの便利な特徴があるため、オプティマイザは、表スキャンよりも範囲スキャンを優先する場合があります。

  • 行が(索引キーで)ソートされて戻される。

  • 行を戻す処理が高速である(特に、表のデータがまばらな場合)。

例9-3では、ソートに範囲スキャンを使用しています。このスキャンでは、条件は評価されません。

列7(その他の条件)

処理の実行時に適用される他の条件を示します。これらの条件は、直接的にスキャンまたは結合で使用されることはありませんが、スキャンまたは結合によって戻された各行で評価されます。

たとえば、例9-3に対して生成された計画のステップ2では、範囲スキャンが表t2で実行されます。そのスキャンの実行時には、条件t2.b <> 0も評価されます。同様に、最後のマージ結合が終了すると、条件t3.b / t1.b > 1の評価が可能になります。

SQLコマンド・キャッシュに格納されているコマンドに関連付けられた問合せ計画の表示

問合せ計画情報は、問合せの監視およびトラブルシューティングに使用します。


ノート:

ttSQLCmdQueryPlan組込みプロシージャを使用するその他の理由については、「パフォーマンス管理およびトラブルシューティングのコマンド」を参照してください。

ttSQLCmdQueryPlan組込みプロシージャを使用すると、コマンド・キャッシュ内の特定の文またはすべての文の問合せ計画が表示されます。キャッシュされているSQL問合せの詳細なランタイム問合せ計画が表示されます。デフォルトでは、すべての問合せ計画が表示されますが、コマンド出力から取得したコマンドIDを指定すると、指定したコマンドの問合せ計画のみが表示されます。


ノート:

特定のコマンドの問合せ計画を表示するには、ttSQLCmdCacheInfo組込みプロシージャで表示されるコマンドIDを指定する必要があります。詳細は、「SQLコマンド・キャッシュに格納されたコマンドの表示」を参照してください。

この組込みプロシージャを実行すると表示される計画データは、次のとおりです。

  • コマンドID

  • 問合せテキスト(最大1024文字)

  • ランタイム問合せ計画での現在の処理のステップ番号

  • 問合せ計画ツリーでの現在の処理のレベル番号

  • 現在のステップの処理名

  • 使用された表の名前

  • 表の所有者

  • 使用された索引の名前

  • 索引条件(使用されており、利用可能な場合)

  • 索引以外の条件(使用されており、利用可能な場合)


ノート:

この情報の表示方法の詳細は、「PLAN表からの問合せ計画の読取り」を参照してください。データのソースは同じでない場合がありますが、情報の位置および説明は、システムPLAN表の問合せ計画と同じです。

ttSQLCmdQueryPlan組込みプロセスには、生データ形式で問合せ計画が表示されます。また、この出力の形式化バージョンには、ttIsql explainコマンドを実行できます。詳細は、「SQL コマンド・キャッシュでの文に関する問合せ計画の表示」を参照してください。

次の例は、ttSQLCmdQueryPlan組込みプロシージャを使用して、SQLコマンド・キャッシュにあるすべてまたは1つのSQL問合せ計画を表示する方法を示しています。

例9-4 すべてのSQL問合せ計画の表示

コマンド・キャッシュに格納されている、コマンドに関連付けられたすべてのSQL問合せ計画を表示するには、ttIsqlユーティリティ内でttSQLCmdQueryPlan組込みプロシージャを使用します。

次の例は、引数を指定しないでttSQLCmdQueryPlan組込みプロシージャを実行した場合の出力を示しています(この場合、すべての有効な問合せの詳細なランタイム問合せ計画が表示されます)。無効な問合せの場合は、問合せ計画は表示されず、問合せテキストが表示されます。

問合せ計画は、簡潔な形式で表示されます。先頭に列見出しを表示するには、ttSQLCmdQueryPlan組込みプロシージャをコールする前にvertical onを実行してください。

ノート: 複雑な式の場合、元の式の出力に問題が生じることがあります。

Command> call ttSQLCmdQueryPlan();

< 528079360, select * from t7 where x7 is not null or exists (select 1 from t2,t3 
where not 'tuf' like 'abc'), <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, 
<NULL>, <NULL> >
< 528079360, <NULL>, 0, 2, RowLkSerialScan                , T7 
, PAT                        ,                                , ,  >
< 528079360, <NULL>, 1, 3, RowLkRangeScan                 , T2 
, PAT                        , I2                             , , NOT(LIKE( tuf 
,abc ,NULL ))  >
< 528079360, <NULL>, 2, 3, RowLkRangeScan                 , T3 
, PAT                        , I2                             , ,  >
< 528079360, <NULL>, 3, 2, NestedLoop                     , 
,                                ,                                , ,  >
< 528079360, <NULL>, 4, 1, NestedLoop(Left OuterJoin)     , 
,                                ,                                , ,  >
< 528079360, <NULL>, 5, 0, Filter                         , 
,                                ,                                , , X7 >
< 527576540, call ttSQLCmdQueryPlan(527973892), <NULL>, <NULL>, <NULL>, <NULL>, 
<NULL>, <NULL>, <NULL>, <NULL> >
< 527576540, <NULL>, 0, 0, Procedure Call                 , 
,                                ,                                , ,  >
< 528054656, create table t2(x2 int,y2 int, z2 int), <NULL>, <NULL>, <NULL>, 
<NULL>, <NULL>, <NULL>, <NULL>, <NULL> >
< 528066648, insert into t2 select * from t1, <NULL>, <NULL>, <NULL>, <NULL>, 
<NULL>, <NULL>, <NULL>, <NULL> >
< 528066648, <NULL>, 0, 0, Insert                         , T2 
, PAT                        ,                                , ,  >
< 528013192, select * from t1 where exists (select * from t2 where x1=x2) or 
y1=1, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL> >
< 528061248, create index i1 on t3(y3), <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, 
<NULL>, <NULL>, <NULL> >
< 528070368, call ttOptSetOrder('t3 t4 t2 t1'), <NULL>, <NULL>, <NULL>, <NULL>, 
<NULL>, <NULL>, <NULL>, <NULL> >
< 528070368, <NULL>, 0, 0, Procedure Call                 , 
,                                ,                                , ,  >
< 528018856, insert into t2 select * from t1, <NULL>, <NULL>, <NULL>, <NULL>, 
<NULL>, <NULL>, <NULL>, <NULL> >
< 527573452, call ttSQLCmdCacheInfo(527973892), <NULL>, <NULL>, <NULL>, <NULL>, 
<NULL>, <NULL>, <NULL>, <NULL> >
< 527573452, <NULL>, 0, 0, Procedure Call                 , 
,                                ,                                , ,  >
< 528123000, select * from t1 where x1 = 1 or x1 = (select x2 from t2,t3 where 
z2=t3.x3), <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL>, <NULL> >
< 528123000, <NULL>, 0, 2, RowLkSerialScan                , T1 
, PAT                        ,                                , ,  >
< 528123000, <NULL>, 1, 6, RowLkRangeScan                 , T2 
, PAT                        , I2                             , ,  >
< 528123000, <NULL>, 2, 6, RowLkRangeScan                 , T3 
, PAT                        , I2                             , ,  Z2 = X3; >
< 528123000, <NULL>, 3, 5, NestedLoop                     , 
,                                ,                                , ,  >
< 528123000, <NULL>, 4, 4, Materialized View              , 
,                                ,                                , ,  >
< 528123000, <NULL>, 5, 3, GroupBy                        , 
,                                ,                                , ,  >
< 528123000, <NULL>, 6, 2, Filter                         , 
,                                ,                                , ,  X1 = 
colum_name; >
< 528123000, <NULL>, 7, 1, NestedLoop(Left OuterJoin)     , 
,                                ,                                , ,  >
< 528123000, <NULL>, 8, 0, Filter                         , 
,                                ,                                , ,  X1 = 1; >

例9-5 単一のSQL問合せ計画の表示

あるコマンドに関連付けられた問合せ計画を表示するには、ttSQLCmdQueryPlan組込みプロシージャの入力として、そのコマンドのコマンドIDを指定します。これにより、SQLコマンド・キャッシュから単一の問合せ計画が表示されます。値が指定されない場合、ttSQLCmdCacheInfo組込みプロシージャはTimesTenキャッシュの現在のすべてのコマンドに関する情報を表示します。

次の例は、コマンドID 528078576で識別されるコマンドの問合せ計画を表示します。これは、簡潔な形式で表示されます(先頭に列見出しを表示するには、ttSQLCmdQueryPlan組込みプロシージャをコールする前にvertical onを実行してください)。

ノート: 複雑な式の場合、元の式の出力に問題が生じます。

Command> call ttSQLCmdQueryPlan( 528078576);
< 528078576, select * from t1 where 1=2 or (x1 in (select x2 from t2, t5 where y2 
in (select y3 from t3)) and y1 in (select x4 from t4)), <NULL>, <NULL>, <NULL>, 
<NULL>, <NULL>, <NULL>, <NULL>, <NULL> >
< 528078576, <NULL>, 0, 4, RowLkSerialScan                , T1 
, PAT                        ,                                , ,  >
< 528078576, <NULL>, 1, 7, RowLkRangeScan                 , T2 
, PAT                        , I2                             , ,  >
< 528078576, <NULL>, 2, 7, RowLkRangeScan                 , T5 
, PAT                        , I2                             , ,  >
< 528078576, <NULL>, 3, 6, NestedLoop                     , 
,                                ,                                , ,  >
< 528078576, <NULL>, 4, 6, RowLkRangeScan                 , T3 
, PAT                        , I1                             ,  ( (Y3=Y2; ) ) ,  >
< 528078576, <NULL>, 5, 5, NestedLoop                     , 
,                                ,                                , ,  >
< 528078576, <NULL>, 6, 4, Filter                         , 
,                                ,                                , ,  X1 = X2; >
< 528078576, <NULL>, 7, 3, NestedLoop(Left OuterJoin)     , 
,                                ,                                , ,  >
< 528078576, <NULL>, 8, 2, Filter                         , 
,                                ,                                , ,  >
< 528078576, <NULL>, 9, 2, RowLkRangeScan                 , T4 
, PAT                        , I2                             , ,  Y1 = X4; >
< 528078576, <NULL>, 10, 1, NestedLoop(Left OuterJoin)     , 
,                                ,                                , ,  >
< 528078576, <NULL>, 11, 0, Filter                         , 
,                                ,                                , ,  >
13 rows found.
Command>

計画生成の変更

問合せ計画を変更する場合、システムPLAN表に存在する問合せ計画のみを変更できます(「システムPLAN表からの問合せ計画の表示」を参照)。問合せ計画を変更した場合、問合せ計画が置き換えられるのではなく、変更内容が含まれる新しい問合せ計画が作成されます。

次の項では、実行計画を変更する理由およびその変更方法について説明します。

実行計画を変更する理由

アプリケーションでは次の2つの理由で、実行計画を変更することがあります。

  • 計画が、速度から見ると最適化されていても、アプリケーションには不適切なため。オプティマイザが最速の実行パスを選択しても、アプリケーション側から見れば、このパスが不適切な場合もあります。たとえば、オプティマイザが、特定の索引を選択すると、索引付けされた表で、更新や削除などの他の処理を同時に実行できなくなる場合があります。このような場合は、アプリケーションによって、これらの索引を使用できなくなる場合があります。

    またオプティマイザが選択した計画で消費するメモリーが、実際の利用可能な容量より多かったり、アプリケーションで割り当てようとする容量より多い場合もあります。たとえば、計画で中間的な処理結果を保持したり、一時索引の作成が必要な場合に、このような容量不足が発生します。

  • 計画のパフォーマンスが最適化されていないため。問合せオプティマイザは、表の内容、利用可能な索引、統計、様々な内部処理の相対的なコストを考慮して最速と考えられる計画を選択します。ただし、これらの情報を評価するとき、オプティマイザは予測やデータの一般化を行うことが多いため、最速の計画が選択されていない場合もあります。このような場合、よりよい計画を作成できるように、アプリケーションはオプティマイザの動作を調整できます。

ヒントが実行計画に与えることができる影響

ヒントを適用して、TimesTen問合せオプティマイザに指示を渡すことができます。問合せに対して最適な実行計画を選択するとき、オプティマイザではこれらのヒントが考慮されます。トランザクション・レベルのヒントは、トランザクション内のODBC SQLPrepare関数またはJDBC PreparedStatementオブジェクトへのすべてのコールに対して有効となります。

  • 特定のヒントが有効になっている状態でコマンドの準備が実行されると、コマンドが自動的に再度準備されても、そのヒントは引き続き適用されます。このような問題は、「最適化を実行するタイミング」で説明したとおり、表の変更、索引の作成または破棄、あるいは統計の変更が行われたときに発生します。

  • ヒントなしでコマンドを準備している場合は、コマンドが自動的に再準備されても、コマンドがその後のヒントの影響を受けることはありません。ヒントを有効にするには、アプリケーションでもう一度ODBC SQLPrepare関数またはJDBC Connection.prepareStatement()メソッドをコールする必要があります。

例9-6 ODBC使用時の結合のチューニング

ODBCを使用する場合に開発者がT1T2の結合を調整するには、次の図に示されているステップを実行することになります。

tune_join.gifの説明が続きます。
図tune_join.gifの説明

実行中は、アプリケーションで次の図に示されているステップが実行されます。

execution_steps.gifの説明が続きます
図execution_steps.gifの説明

例9-7 JDBC使用時の結合のチューニング

JDBCを使用する場合に開発者がT1T2の結合を調整するには、次の図に示されているステップを実行することになります。

jdbc_steps.gifの説明が続きます
図jdbc_steps.gifの説明

実行中は、アプリケーションで次の図に示されているステップが実行されます。

jdbc_exec_steps.gifの説明が続きます
図jdbc_exec_steps.gifの説明

オプティマイザ・ヒントを使用して実行計画を変更する

ヒントを適用して、TimesTen問合せオプティマイザに次のように指示を渡すことができます。

  • 特定のSQL文のみにヒントを適用するには、文レベルのオプティマイザ・ヒントを使用します。

  • トランザクション全体にヒントを適用するには、適切なTimesTen組込みプロシージャとともにトランザクション・レベルのオプティマイザ・ヒントを使用します。

  • TimesTen接続全体にヒントを適用するには、接続レベルのオプティマイザ・ヒントを使用します。

オプティマイザ・ヒントの優先順位は、文レベルのヒント、トランザクション・レベルのヒント、接続レベルのヒントとなります。


ノート:

TimesTenは読取り処理および書込み処理を同時に最適に処理します。ttOptSetFlag ('tblLock',1)などのトランザクション・レベル・オプティマイザ・ヒントまたは/*+ tt_tbllock(1) tt_rowlock(0) */などの文レベル・オプティマイザ・ヒントを使用すると、読取り専用同時実行性に対して読取り処理を最適化できます。読取り最適化処理と同時に処理する書込み処理は競合する可能性があります。

ttDbWriteConcurrencyModeSet組込みプロシージャにより、同時書込み処理時に読取り最適化を制御できます。詳細は、「同時書込み処理時の読取り最適化の制御」を参照してください。


次の項では、ヒントの適用手順について説明します。

SQL文への文レベルのオプティマイザ・ヒントの適用

文レベルのオプティマイザ・ヒントは特殊なフォーマットのSQLコメントで、SQLオプティマイザに対する命令が含まれます。文レベルのオプティマイザ・ヒントは、適用対象となるSQL文の中に、次のいずれかの方法で適用できます。

  • /*+ */ ヒントは複数行にわたって定義できます。ヒントはコメント構文で囲む必要があります。プラス記号(+)はヒントの開始を示します。

  • --+ ヒントは1行で、プラス記号(+)の後に指定する必要があります。

文レベルのオプティマイザ・ヒントは、SELECTINSERTUPDATEMERGEDELETECREATE TABLE AS SELECTまたはINSERT ... SELECT文の中に指定できます。SQL VERBのすぐ後で、コメント構文内にヒントを指定する必要があります。

文レベルのオプティマイザ・ヒントに固有の詳細は、『Oracle TimesTen In-Memory Database SQLリファレンス』の文レベルのオプティマイザ・ヒントに関する項を参照してください。TimesTen Scaleout固有のオプティマイザ・ヒントについては、Oracle TimesTen In-Memory Database Scaleoutユーザーズ・ガイドのオプティマイザ・ヒントの使用を参照してください。


ノート:

文レベルのオプティマイザ・ヒントを誤って指定した場合、そのヒントはTimesTenによって無視され、エラーは発生しません。競合するヒントを定義すると、その文で競合するヒントは一番右のヒントによってすべて上書きされます。

トランザクションへのトランザクション・レベルのオプティマイザ・ヒントの適用

トランザクション内のすべての文に対する問合せオプティマイザの動作を変更するには、ODBCプロシージャ・コール・インタフェースを使用して、アプリケーションで次の組込みプロシージャのいずれかをコールします。


ノート:

トランザクション・レベルのオプティマイザのヒントについて、自動コミットがオフになっていることを確認してください。オプティマイザのすべてのフラグは、トランザクションがコミットまたはロールバックされた時点でそれぞれのデフォルト値にリセットされます。自動コミットがオンになっている状態でオプティマイザ・フラグを設定しても、各文は固有のトランザクション内で実行されるため、そのフラグは無視されます。

  • ttOptSetFlag: 特定のオプティマイザ・パラメータを設定します。トランザクション・レベルのオプティマイザ・ヒントを持つオプティマイザに、特定の問合せの最適化に関する推奨事項を提供します。

  • ttOptGetFlag — データベースに設定されている既存のトランザクション・レベルのヒントを確認します。

  • ttOptSetOrder: アプリケーションで、表の結合順番を指定できるようにします。

  • ttOptUseIndex: アプリケーションで、使用する索引の指定または特定の索引の使用の無効化をできるようにします。つまり、問合せの各相関について考慮する必要がある索引を指定します。

  • ttOptClearStatsttOptEstimateStatsttOptSetColIntvlStatsttOptSetTblStatsttOptUpdateStats: TimesTenでアプリケーションのデータに対して保持される統計を操作します。統計は、問合せオプティマイザによって様々な処理のコスト見積りに使用されます。

これらの組込みプロシージャの中には、ユーザーが実行対象のオブジェクトに対する権限を持っている必要のあるものがあります。これらの組込みプロシージャと必要な権限の詳細は、『Oracle TimesTen In-Memory Databaseリファレンス』の組込みプロシージャに関する説明を参照してください。

次の例は、ttOptSetFlag組込みプロシージャの使用方法を、ODBCとJDBCのそれぞれの場合について示しています。


ノート:

ttIsqlユーティリティを使用して、オプティマイザの設定を試すこともできます。tryで始まるコマンドは、トランザクション・レベルのオプティマイザのヒントを制御します。現在のトランザクション・レベルのオプティマイザのヒント設定を確認するには、optprofileコマンドを使用します。

例9-8 JDBCでのttOptSetFlagの使用

次のJDBCの例は、ttOptSetFlagを使用して、オプティマイザがマージ結合を選択しないようにする方法を示しています。

import java.sql.*; 
class Example 
{ 
 public void myMethod() { 
    CallableStatement cStmt; 
    PreparedStatement pStmt;
     . . . . . 
    try {
         . . . . . . . 
        // Prevent the optimizer from choosing Merge Join 
        cStmt = con.prepareCall("{ 
            CALL ttOptSetFlag('MergeJoin', 0)}"); 
        cStmt.execute();
        // Next prepared query 
        pStmt=con.prepareStatement( 
        "SELECT * FROM Tbl1, Tbl2 WHERE Tbl1.ssn=Tbl2.ssn");
        . . . . . . . 
        catch (SQLException ex) { 
            ex.printStackTrace(); 
        } 
    } 
    . . . . . . .
}

例9-9 ODBCでのttOptSetFlagの使用

次のODBCの例は、ttOptSetFlagを使用して、オプティマイザがマージ結合を選択しないようにする方法を示しています。

#include <sql.h>
SQLRETURN rc;
SQLHSTMT hstmt; fetchStmt;
....
rc = SQLExecDirect (hstmt, (SQLCHAR *)
     "{CALL ttOptSetFlag (MergeJoin, 0)}",
     SQL_NTS)
/* check return value */
...
rc = SQLPrepare (fetchStmt, ...)
/* check return value */
...

TimesTen接続への接続レベルのオプティマイザ・ヒントの適用

特定の接続のすべての文に対する問合せオプティマイザの動作を変更するには、OptimizerHint接続属性を定義します。OptimizerHint接続属性の値は、文レベルのオプティマイザ・ヒントと同じ形式を使用する文字列ですが、/*+*/および--+のデリミタがありません。

接続レベルのオプティマイザ・ヒントにコメントを含めることはできません。

トランザクション・レベルのオプティマイザ・ヒントによって、現在のトランザクションの接続レベルのオプティマイザ・ヒントが上書きされます。コミット後は、トランザクション・レベルのオプティマイザ・ヒントが失われ、接続レベルのオプティマイザ・ヒントが有効になります。文レベルのオプティマイザ・ヒントによって、文の範囲のトランザクション・レベルのオプティマイザ・ヒントおよび接続レベルのオプティマイザ・ヒントが上書きされます。これは接続属性であるため、ttConfigurationユーティリティは、接続レベルのオプティマイザ・ヒントを示します。


ノート:

クライアント・サーバー設定では、この接続属性のクライアント接続設定によって、この属性のサーバーDSN設定が上書きされます。

例9-10 接続レベルのオプティマイザ・ヒントの使用方法

この例では、TT_RowLockTT_TblLockおよびTT_MergeJoinを使用して、行ロックを有効にし、表ロックおよびマージ結合を無効にする方法を示しています。/disk1/timestentimesten_homeであることに注意してください。

...
[database1]
Driver=/disk1/timesten/install/lib/libtten.so
DataStore=/disk1/timesten/info/DemoDataStore/database1
PermSize=128
TempSize=64
DatabaseCharacterSet=AL32UTF8
OptimizerHint= TT_RowLock (1) TT_TblLock (0) TT_MergeJoin (0)
...

例9-11 接続レベルのオプティマイザ・ヒントとしてTT_INDEXを使用する方法

TimesTenでは、接続属性でのセミコロン(;)文字の使用はサポートされていません。したがって、接続レベルで複数のTT_INDEXオプティマイザ・ヒントを使用する場合は、文レベルで使用する構文と同じ構文を使用できません。

たとえば、TT_INDEX(EMPLOYEES,EMP_NAME_IX,1;EMPLOYEES,EMP_MANAGER_IX,1)は文レベルのオプティマイザ・ヒントとしては有効ですが、接続レベルのオプティマイザ・ヒントとしては無効です。同じ行に複数のTT_INDEXオプティマイザ・ヒントが指定されている場合、TimesTenによってこれらはマージされます。したがって、TT_INDEX(EMPLOYEES,EMP_NAME_IX,1) TT_INDEX(EMPLOYEES,EMP_MANAGER_IX,1)は、TT_INDEX(EMPLOYEES,EMP_NAME_IX,1;EMPLOYEES,EMP_MANAGER_IX,1)に相当します。

この例では、接続レベルで複数のTT_INDEXオプティマイザ・ヒントを使用する方法を示しています。/disk1/timestentimesten_homeであることに注意してください。

...
[database1]
Driver=/disk1/timesten/install/lib/libtten.so
DataStore=/disk1/databases/info/DemoDataStore/database1
PermSize=128
TempSize=64
DatabaseCharacterSet=AL32UTF8
OptimizerHint= TT_INDEX(EMPLOYEES,EMP_NAME_IX,1) TT_INDEX(EMPLOYEES,EMP_MANAGER_IX,1)
...

OptimizerHint接続属性の詳細は、『Oracle TimesTen In-Memory Databaseリファレンス』のOptimizerHintに関する項を参照してください。