ヘッダーをスキップ
Oracle® TimesTen In-Memory Databaseオペレーション・ガイド
リリース11.2.1
B56047-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

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

コスト・ベースのTimesTen問合せオプティマイザでは、アプリケーションの表の情報と使用可能な索引を使用して、データへのファスト・パスを選択します。アプリケーション開発者は、オプティマイザが選択したプランを確認して、索引が適切に使用されているかをチェックできます。またアプリケーション開発者は、必要に応じて、オプティマイザが別のプランを選択するように設定を変更できます。

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

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

1つのコマンドが何度も最適化されることがあるため、TimesTenがどのようなタイミングで問合せの最適化を実行するのか理解しておくことをお薦めします。

オプティマイザは、ODBCのSQLPrepareまたはSQLExecDirect関数あるいはJDBCのいずれかの実行メソッドによってSELECT文、UPDATE文、DELETE文、INSERT SELECT文またはCREATE MATERIALIZED VIEW文が準備されると、必ず起動されます。作成された計画は、それを無効にするイベントが発生するか、またはそのコマンドがアプリケーションによって破棄されるまで保持されます。コマンドは、次の場合に無効になります

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


注意:

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

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

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

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

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

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

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

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

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

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

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


注意:

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

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

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

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

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

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

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

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

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

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

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

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

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

  • プライベート接続ID。

  • 実行回数のカウンタ。

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

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

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

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

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

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

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

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

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

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

Command> call ttsqlCmdCacheInfo;
< 528079360, 2048, 0, 1, 0, 1, 2168, PAT                        , select * from 
t7 where x7 is not null or exists (select 1 from t2,t3 where not 'tuf' like 
'abc') >
< 527609108, 2048, 0, 1, 0, 1, 2960, PAT                        , select * from 
t1 where x1 = (select x2 from t2 where z2 in (1,3) and y1=y2) order by 1, 2, 3 >
< 528054656, 2048, 0, 1, 0, 1, 1216, PAT                        , create table 
t2(x2 int,y2 int, z2 int) >
< 528066648, 2048, 0, 1, 0, 1, 1176, PAT                        , insert into t2 
select * from t1 >
< 528013192, 2048, 0, 1, 0, 1, 1848, PAT                        , select * from 
t1 where exists (select * from t2 where x1=x2) or y1=1 >
< 527582620, 2048, 0, 1, 0, 1, 1240, PAT                        , insert into t2 
select * from t1 >
< 527614292, 2048, 0, 1, 0, 1, 2248, PAT                        , select * from 
t1 where exists (select x2 from t2 where x1=x2) order by 1, 2, 3 >
< 528061248, 2048, 0, 1, 0, 1, 696, PAT                        , create index i1 
on t3(y3) >
< 528070368, 2048, 0, 1, 0, 1, 824, PAT                        , call 
ttOptSetOrder('t3 t4 t2 t1') >
< 528018856, 2048, 0, 1, 0, 1, 984, PAT                        , insert into t2 
select * from t1 >
< 527606460, 2048, 0, 1, 0, 1, 2624, PAT                        , select * from 
t1 where x1 = (select x2 from t2 where y1=y2) order by 1, 2, 3 >
< 528123000, 2048, 0, 1, 0, 1, 3616, PAT                        , select * from 
t1 where x1 = 1 or x1 = (select x2 from t2,t3 where z2=t3.x3) >
< 528074624, 2048, 0, 1, 0, 1, 856, PAT                        , call 
ttOptSetOrder('t4 t2 t3 t1') >
< 527973892, 2048, 0, 1, 0, 1, 2872, PAT                        , select * from 
t1 where x1 in (select x2 from t2) or x1 in (select x3 from t3) order by 1, 2, 3 >
< 527953876, 2048, 0, 1, 0, 1, 3000, PAT                        , select * from 
t1 where x1 = (select x2 from t2) order by 1, 2, 3 >
< 527603900, 2048, 0, 1, 0, 1, 2440, PAT                        , select * from 
t1 where x1 in (select x2 from t2 where y1=y2) order by 1, 2, 3 >
< 528093308, 2048, 0, 1, 0, 1, 3608, PAT                        , select * from 
t1 where x1 = 1 or x1 = (select x2 from t2,t3 where z2=t3.x3 and t3.z3=1) >
< 528060608, 2048, 0, 1, 0, 1, 696, PAT                        , create index i1 
on t2 (y2) > 

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

ttSqlCmdCacheInfoに入力としてコマンドIDを指定すると、SQLコマンド・キャッシュから単一のSQLコマンドが表示されます。コマンドIDを確認するには、引数なしでこの組込みプロシージャを実行します。コマンドIDは、表示される最初の列です。

次の例は、コマンドID 527973892で識別されるSQLコマンドを表示します。簡潔な形式で表示されます。データの先頭に列見出しを表示するには、ttsqlCmdCacheInfo組込みプロシージャを実行する前にvertical onを実行してください。

Command> call ttsqlCmdCacheInfo(527973892);
< 527973892, 2048, 0, 1, 0, 1, 2872, PAT                        , select * from 
t1 where x1 in (select x2 from t2) or x1 in (select x3 from t3) order by 1, 2, 3 >
1 row found.

SQL問合せ計画の表示

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

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

オプティマイザによって、問合せ計画が準備されます。実行する最後のSQLコマンド(準備済のSELECTUPDATEDELETEINSERT SELECTCREATE TABLECREATE MATERIALIZED VIEWなど)の計画がシステムPLAN表に格納されるように指定できます。

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

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

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

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

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

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

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

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

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

システムPLAN表の計画を表示するには、その前に、GenPlanフラグを指定してttOptSetFlag組込みプロシージャをコールします。このコールによって、それ以降にODBC SQLPrepare関数またはJDBC Connection.prepareStatementメソッドのコールがトランザクションにあれば、そのすべてのコールから得られた計画が現在のSYS.PLAN表に保存されるようになります。


注意:

AUTOCOMMITが設定されていないことを確認してください。設定されている場合は、このコマンドの実行後に現在のトランザクションが終了してしまい、次のトランザクションの準備を実行できなくなります。

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

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

たとえば、ttIsqlユーティリティを使用して問合せやオプティマイザ・ヒントを試してみます。オプティマイザの計画を表示するには、次のコマンドを発行します。

autocommit 0;
showplan 1;

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

計画の生成を有効にしてコマンドの準備が終了すると、SYS.PLAN表の1つ以上の行にコマンドの計画が格納されます。その行数は、コマンドがどの程度複雑かによって変わります。それぞれの行には、列が7つあります。詳細は、Oracle TimesTen In-Memory Databaseのシステム表および制限についてのマニュアルのシステム表に関する説明を参照してください。

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

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

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 TblLkTtreeScan T1 IX1

2 3 TblLkTtreeScan T2 IX2(D)
T2.B <> 0
3 2 MergeJoin

T1.A = -T2.A
4 2 TblLkTtreeScan T3 IX3(D)

5 1 MergeJoin

T2.A = T3.A T3.B/T1.B > 1

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

PLAN表の各列の説明

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

列1(ステップ)

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

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

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

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

列2(レベル)

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

結合ツリーの例
jointree.gifの説明

列3(処理)

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

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

列4(表名)

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

列5(索引名)

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

列6(条件)

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

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

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

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

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

列7(その他の条件)

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

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

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

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


注意:

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

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


注意:

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

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

  • コマンドID

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

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

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

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

  • 使用された表の名前

  • 表の所有者

  • 使用された索引の名前

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

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


注意:

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

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

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

例10-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, RowLkTtreeScan                 , T2                             
, PAT                        , I2                             , , NOT(LIKE( tuf 
,abc ,NULL ))  >
< 528079360, <NULL>, 2, 3, RowLkTtreeScan                 , 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, RowLkTtreeScan                 , T2                             
, PAT                        , I2                             , ,  >
< 528123000, <NULL>, 2, 6, RowLkTtreeScan                 , 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; >

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

あるSQLコマンドに関連付けられた問合せ計画を表示するには、ttSqlCmdQueryPlan組込みプロシージャの入力として、そのSQLコマンドのコマンドIDを指定します。これにより、SQLコマンド・キャッシュから単一の問合せ計画が表示されます。コマンドIDを確認するには、引数なしでこのttSqlCmdCacheInfo組込みプロシージャを実行します。コマンドIDは、表示される最初の列です。

次の例は、コマンドID 528078576で識別されるSQLコマンドの問合せ計画を表示します。問合せ計画は簡潔な形式で表示されます。データの先頭に列見出しを表示するには、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, RowLkTtreeScan                 , T2                             
, PAT                        , I2                             , ,  >
< 528078576, <NULL>, 2, 7, RowLkTtreeScan                 , T5                             
, PAT                        , I2                             , ,  >
< 528078576, <NULL>, 3, 6, NestedLoop                     ,                                
,                                ,                                , ,  >
< 528078576, <NULL>, 4, 6, RowLkTtreeScan                 , 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, RowLkTtreeScan                 , 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オプティマイザの組込みプロシージャの1つへのコールで指定されると、トランザクション内のODBC SQLPrepare関数またはJDBC PreparedStatementオブジェクトへのすべてのコールに対して有効となります。これらのヒントの指定方法については、「実行計画の生成を変更する方法」を参照してください。


注意:

AUTOCOMMITが設定されていないことを確認してください。設定されている場合は、ttOptSetFlagプロシージャの実行後に現在のトランザクションが終了してしまい、次のトランザクションの準備を実行できなくなります。

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

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

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

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

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

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

結合をチューニングするためのアプリケーション手順
execution_steps.gifの説明

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

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

JDBC内での結合のチューニング
jdbc_steps.gifの説明

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

JDBC実行手順
jdbc_exec_steps.gifの説明

実行計画の生成を変更する方法

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

  • ttOptSetFlag: 特定のオプティマイザ・パラメータを設定します。

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

  • ttOptUseIndex: アプリケーションで、使用する索引の指定または特定の索引の使用の無効化を実行できるようにします。

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

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

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


注意:

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

例10-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(); 
        } 
    } 
    . . . . . . .
}

例10-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 */
...