コスト・ベースのTimesTen問合せオプティマイザでは、アプリケーションの表の情報と使用可能な索引を使用して、データへのファスト・パスを選択します。アプリケーション開発者は、オプティマイザが選択したプランを確認して、索引が適切に使用されているかをチェックできます。またアプリケーション開発者は、必要に応じて、オプティマイザが別のプランを検討するように、オプティマイザの動作に影響を与えるヒントを提供できます。
この章の内容は次のとおりです。
複数の実行計画が可能な場合、TimesTenによってSQL文用のオプティマイザが起動されます。オプティマイザは、最適と判断した計画を選択します。この計画は、文がアプリケーションによって無効にされるか削除されるまで保持されます。
コマンドが使用するオブジェクトが破棄された
コマンドが使用するオブジェクトが変更された
コマンドが参照する表またはビューの索引が破棄された
コマンドが参照する表またはビューに索引が作成された
次のいずれかの方法を使用して、文を手動で無効化できます。
ttOptCmdCacheInvalidate
組込みプロシージャを使用してSQLコマンド・キャッシュ内の文を無効化します。詳細は、「コマンドの無効化をSQLコマンド・キャッシュで制御する」を参照してください。
ttOptUpdateStats
またはttOptEstimateStats
組込みプロシージャで、invalidation
オプションを1に設定します。これらの組込みプロシージャによって、指定した表または現在のユーザーが所有するすべての表の統計も更新されます。
注意: 統計を計算するときの詳細は、「正確な統計または推定統計の計算」を参照してください。また、『Oracle TimesTen In-Memory Databaseリファレンス』のttOptUpdateStatsまたはttOptEstimateStatsに関する説明も参照してください。 |
無効になった文は、通常、再実行される直前に再度自動的に準備されます。つまり、その時点でオプティマイザが再度起動され、場合によっては新しい計画が作成されます。したがって、1つのコマンドが何度も準備されることがあります。
注意: JDBCを使用しているときは、表が変更された場合に、文を手動で再度準備する必要があります。 |
たとえば、文で参照していた表が破棄され、同じ名前の表が作成されたときには、文を手動で準備することが必要な場合があります。文を手動で準備する場合は、準備文を、共有できるようにコミットする必要があります。文が、無効なため再コンパイルされる場合、および参照されているいずれかの表で使用されているDDLが再コンパイルに必要な場合は、準備文をコミットしてコマンド・ロックを解放する必要があります。
たとえば、ODBCでは、表T1
とT2
を結合するコマンドによって、次のような処理が行われます。
アクション | 説明 |
---|---|
SQLPrepare |
コマンドが準備されます。 |
SQLExecute |
コマンドが実行されます。 |
SQLExecute |
コマンドが再実行されます。 |
T1に対する索引の作成 | コマンドが無効化されます。 |
SQLExecute |
コマンドが再度準備され、実行されます。 |
SQLExecute |
コマンドが再実行されます。 |
T1に対するttOptUpdateStats |
コマンドが無効になります(無効フラグがttOptUpdateStats プロシージャに渡された場合)。 |
SQLExecute |
コマンドが再度準備され、実行されます。 |
SQLExecute |
コマンドが再実行されます。 |
SQLFreeStmt |
コマンドが破棄されます。 |
JDBCでは、表T1
とT2
を結合するコマンドによって、次のような処理が行われます。
アクション | 説明 |
---|---|
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コマンド・キャッシュに格納されているこれらのコマンドを1つ以上取得できます。
注意: この項では、SQLコマンド・キャッシュに格納されたコマンドの表示方法について説明します。これらのコマンドに関連付けられた問合せ計画の表示方法については、「SQLコマンド・キャッシュに格納されているコマンドに関連付けられた問合せ計画の表示」を参照してください。 |
次の項では、SQLコマンド・キャッシュに格納されているコマンドを表示する方法について説明します。
1つ以上のコマンドまたはその問合せ計画の詳細は、ttSQLCmdCacheInfo
およびttSQLCmdQueryPlan
組込みプロシージャで表示できます。問合せ計画情報は、問合せの監視およびトラブルシューティングに使用します。
コマンドおよび問合せ計画を表示すると、次の作業に役立ちます。
索引スキャンを使用していない更新または削除の検出。
すべての計画を確実に最適化することを目的とする、実行中の問合せの問合せ計画の監視。
SQL文を準備しないアプリケーション、または同じ文を複数回再準備するアプリケーションの検出。
コマンド・キャッシュ内でパフォーマンスの評価に使用されている領域の割合の検出。
TimesTenデータベースに対して実行されたコマンドは、SQLコマンド・キャッシュにキャッシュされます。ttSQLCmdCacheInfo
組込みプロシージャを使用すると、TimesTen SQLコマンド・キャッシュにキャッシュされた特定のコマンドまたはすべてのコマンドが表示されます。デフォルトではすべてのコマンドが表示されますが、コマンドIDを指定すると、そのコマンドのみが取得されて表示されます。
コマンド・データは、次の形式で保存されます。
コマンドID。特定のコマンドまたはそのコマンドに関連付けられた問合せ計画を取得する場合に使用されます。
プライベート接続ID。
実行回数のカウンタ。
ユーザーがこの文を準備した回数のカウンタ。
ユーザーがこのSQL文を再準備した回数のカウンタ。
解放可能かどうかのステータスで、この値が1の場合、サブデーモンはガベージ・コレクタで領域を解放できます。値が0の場合、領域は解放可能ではありません。
キャッシュ内でこのコマンドに対して割り当てられている合計サイズ(バイト)。
コマンドを作成したユーザー。
最大1024文字の問合せテキスト。
この文のために内部的に行われたフェッチの実行回数です。
文が開始したときのタイムスタンプです。
最大実行時間が秒単位で表示されます。
最後に測定された実行時間が秒単位で表示されます。
最小実行時間が秒単位で表示されます。
すべてのコマンドのリストの末尾には、キャッシュ内に格納されていたコマンド数を示すステータスが出力されます。
次の例は、ttSQLCmdCacheInfo
組込みユーティリティを使用して、SQLコマンド・キャッシュにあるすべてまたは単一のコマンドを表示する方法を示しています。
例9-1 SQLコマンド・キャッシュ内のすべてのコマンドの表示
この例では、ttIsql
内で引数を指定しないでttSQLCmdCacheInfo
組込みプロシージャを実行し、キャッシュされたすべてのコマンドを表示します。コマンドは、簡潔な形式で表示されます。各列に列名が付加された情報を表示するには、ttSQLCmdCacheInfo
プロシージャをコールする前にvertical on
を実行してください。
Command> call ttSQLCmdCacheInfo; < 110168040, 2048, 2, 2, 0, 1, 2792, CACHEUSER , create writethrough cache group update_orders from ordertab (orderid number(10) not null primary key, custid number (6) not null), 0, 2013-01-04 13:13:47.614000, 4.908, 4.908, 0 > < 35681280, 2048, 0, 8, 0, 1, 5256, SYS , select null from sys.obj$ where obj#=:1 and type#=:2 and obj# not in (select p_obj# from dependency$ where p_obj# = sys.obj$.obj#), 0, <NULL>, 0, 0, 0 > < 110189568, 2048, 1, 1, 0, 1, 4304, PAT , call ttstatsconfig('connsamplefactor',0), 0, 2013-01-08 08:33:18.969000, 0, 0, 0 > < 110176976, 2048, 1, 1, 0, 1, 4328, PAT , call ttstatsconfig('sqlcmdsamplefactor',0), 2, 2013-01-08 08:32:31.751000, .000664, .000664, .000664 > < 110193800, 2048, 1, 1, 0, 1, 4328, PAT , call ttstatsconfig('connsamplefactor','1,0'), 2, 2013-01-08 08:33:29.578000, 0, 0, 0 > < 35291992, 2048, 0, 1, 0, 1, 2568, SYS , select sys25 from sys.tables where cachegroup = ?, 0, <NULL>, 0, 0, 0 > < 40815768, 2048, 2, 1, 0, 0, 3944, SYS , select u.user#, u.password, u.identification, u.astatus from sys.user$ u where u.name = :name and u.type# = 1, 2, 2013-01-04 13:03:29.262000, 0, 0, 0 > < 110243304, 2048, 0, 2, 0, 1, 1208, PAT , call ttcmdcacheinfo(), 0, <NULL>, 0, 0, 0 > < 35287688, 2048, 1, 1, 0, 1, 4232, SYS , select cgname, cgowner, cgid, refresh_mode, refresh_state, refresh_interval, sys10, TBLCNT, CGATTRIBUTES from sys.cache_group, 1, 2013-01-04 13:04:33.549000, 0, 0, 0 > < 110255264, 2048, 2, 2, 0, 1, 3048, SYS , select order#,columns,types from sys.access$ where d_obj#=:1, 2, 2013-01-08 08:40:44.633000, 0, 0, 0 > < 110185240, 2048, 1, 1, 0, 1, 4312, PAT , call ttstatsconfig('connsamplefactor','1,5'), 2, 2013-01-08 08:33:09.505000, 0, 0, 0 > < 35031664, 2048, 1, 1, 0, 1, 2232, CACHEUSER , call ttCacheUidPwdSet('cacheuser','oracle'), 0, 2013-01-04 13:03:43.615000, .326, .326, 0 > < 110229864, 2048, 2, 2, 0, 1, 4240, PAT , call ttstatsconfig('sqlcmdsamplefactor'), 4, 2013-01-08 08:32:10.638000, .000082, .000082, .000082 > < 40819648, 2048, 1, 1, 0, 0, 3904, SYS , select 1 from sys.sysauth$ s where (s.grantee# = :userid or s.grantee# = 1) and (s.privilege# = :priv or s.privilege# = 67), 1, 2013-01-04 13:03:29.262000, 0, 0, 0 > < 35038832, 2048, 1, 2, 0, 1, 3336, CACHEUSER , create writethrough cache group update_cust from active_customer (custid number (6) not null primary key, name varchar2(50), addr varchar2(100), zip varchar2(12)), 0, 2013-01-04 13:06:53.452000, 19.917, 19.917, 0 > < 110270264, 2048, 4, 4, 0, 1, 3888, SYS , select piece#,length,piece from sys.idl_ub2$ where obj#=:1 and part=:2 and version=:3 order by piece#, 34, 2013-01-08 08:40:44.633000, 0, 0, 0 > < 110266280, 2048, 4, 4, 0, 1, 3888, SYS , select piece#,length,piece from sys.idl_char$ where obj#=:1 and part=:2 and version=:3 order by piece#, 14, 2013-01-08 08:40:44.633000, 0, 0, 0 > < 35034128, 2048, 1, 1, 0, 1, 1688, CACHEUSER , call ttGridCreate('ttGrid'), 0, 2013-01-04 13:04:00.891000, 0, 0, 0 >
例9-2 単一のSQLコマンドの表示
ttSQLCmdCacheInfo
に入力としてコマンドIDを指定すると、SQLコマンド・キャッシュから単一のコマンドが表示されます。ttSQLCmdCacheInfo
組込みプロシージャにコマンドIDを入力しなかった場合、現在のすべてのコマンドに関する情報が表示されます。このとき、コマンドIDが出力の最初の列に表示されます。
次の例は、コマンドID 527973892
で識別されるコマンドを表示します。これは、簡潔な形式で表示されます(先頭に列見出しを表示するには、組込みの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.
コマンドの問合せ計画を表示するには、最新の問合せ計画をシステムPLAN
表に格納する方法か、またはSQLコマンド・キャッシュにキャッシュされたすべてのコマンドとその問合せ計画を表示する方法のいずれかを使用します。次の項では、この2つの方法について説明します。
オプティマイザによって、問合せ計画が準備されます。実行する最後のSQL文について、計画がシステムのPLAN
表に格納されるように指示することができます。
計画を生成してシステムPLAN
表に格納するようにTimesTenに指示します。
文の準備で、その文に対してODBC S
SQLPrepare
関数またはJDBC Connection.prepareStatement
メソッドをコールします。PLAN
表に計画が格納されます。
SYS.PLAN
表に生成された計画を読み取ります。
格納された計画は、コマンドの再準備が実行されるたびに自動的に更新されます。再準備は、次の1つ以上の状況が発生すると自動的に実行されます。
文内の表が変更された場合。
索引が作成または廃棄された場合。
アプリケーションで、統計の更新時に、ttOptUpdateStats
組込みプロシージャのinvalidate
オプションを使用してコマンドが無効化された場合。
ユーザーがttOptCmdCacheInvalidate
組込みプロシージャを使用してコマンドを無効にした場合。
注意: 詳細は、「コマンドの無効化をSQLコマンド・キャッシュで制御する」を参照してください。組込みプロシージャの詳細は、『Oracle TimesTen In-Memory Databaseリファレンス』のttOptUpdateStatsおよびttOptCmdCacheInvalidateに関する説明を参照してください。 |
このような場合は、計画がどのように変更されたかをPLAN
表で確認します。
システムの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
表内にある場合でも、計画は作成されます。
ttIsql
のshowplan
を使用して問合せおよびオプティマイザのヒントをテストできます。これにより計画生成が可能になるとともに、トランザクション内にある問合せ計画も示します。自動コミット・モードを無効にする必要があります。
autocommit 0; showplan 1;
計画の生成を有効にしてコマンドの準備が終了すると、SYS.PLAN
表の1つ以上の行にコマンドの計画が格納されます。表の行数は、コマンドがどの程度複雑かによって変わります。それぞれの行には、『Oracle TimesTen In-Memory Databaseシステム表およびビュー・リファレンス』のシステム表に関する説明のとおり、列が7つあります。
例9-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 | 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表の各列の説明」を参照してください。
処理の順序を示します(常に1から開始)。例9-3は、次の順序で表ロック範囲スキャンを使用します。
表T1
のIX1で、表ロック範囲スキャンを実行します。
表T2
のIX2で、表ロック範囲スキャンを実行します。
T1
とT2
などでマージ結合を実行します。
実行される処理のタイプを示します。このフィールドで使用される可能性がある値とそれぞれが表す表スキャンのタイプの詳細は、『Oracle TimesTen In-Memory Databaseシステム表およびビュー・リファレンス』の「システム表」のSYS.PLAN
を参照してください。
オプティマイザが実行した処理内容がすべてユーザーに表示されるわけではありません。パフォーマンスの解析にとって重要な処理のみがSYS.PLAN
表に表示されます。TblLk
は、シリアライズ可能分離モードまたはコミット読取り分離モードでの実行時に使用可能なオプティマイザ・ヒントです。表ロックは、準備時に行ロックが無効になっている場合にのみスキャン時に使用されます。
使用される索引を示します。この列は、処理が、既存の索引(ハッシュまたは範囲スキャン)を使用する索引スキャンの場合にのみ使用されます。それ以外の場合、この列はNULL
です。スキャンが降順(小から大ではなく、大から小)の場合、範囲索引の名前に「(D)」が付きます。
処理に条件が含まれる場合に、その条件を示します。条件が使用されるのは、索引スキャンとMergeJoin
の処理のみです。条件文字列は、1,024文字に制限されています。
範囲スキャンの場合、この列は条件がないことを表すNULL
になる場合があります。範囲スキャンに、フィルタリングの他に次のような2つの便利な特徴があるため、オプティマイザは、表スキャンよりも範囲スキャンを優先する場合があります。
行が(索引キーで)ソートされて戻される。
行を戻す処理が高速である(特に、表のデータがまばらな場合)。
例9-3では、ソートに範囲スキャンを使用しています。このスキャンでは、条件は評価されません。
処理の実行時に適用される他の条件を示します。これらの条件は、直接的にスキャンまたは結合で使用されることはありませんが、スキャンまたは結合によって戻された各行で評価されます。
たとえば、例9-3に対して生成された計画のステップ2では、範囲スキャンが表T2
で実行されます。そのスキャンの実行時には、条件T2.B <> 0
も評価されます。同様に、最後のマージ結合が終了すると、条件T3.B / T1.B > 1
の評価が可能になります。
問合せ計画情報は、問合せの監視およびトラブルシューティングに使用します。
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を使用する場合に開発者がT1
とT2
の結合を調整するには、次の図に示されている手順を実行することになります。
実行中は、アプリケーションで次の図に示されている手順が実行されます。
例9-7 JDBC使用時の結合のチューニング
JDBCを使用する場合に開発者がT1
とT2
の結合を調整するには、次の図に示されている手順を実行することになります。
実行中は、アプリケーションで次の図に示されている手順が実行されます。
ヒントを適用して、TimesTen問合せオプティマイザに次のように指示を渡すことができます。
特定のSQL文のみにヒントを適用するには、文レベルのオプティマイザ・ヒントを使用します。
トランザクション全体にヒントを適用するには、適切なTimesTen組込みプロシージャとともにトランザクション・レベルのオプティマイザ・ヒントを使用します。
注意: TimesTenは読取り問合せおよび書込み問合せを同時に最適に処理します。ttOptSetFlag ('tblLock',1) などのトランザクション・レベル・オプティマイザ・ヒントまたは/*+ tt_tbllock(1) tt_rowlock(0) */ などの文レベル・オプティマイザ・ヒントを使用すると、読取り専用同時実行性に対して読取り問合せを最適化できます。読取り最適化問合せと同時に処理する書込み問合せは競合する可能性があります。
|
次の項では、ヒントの適用手順について説明します。
文レベルのオプティマイザ・ヒントは特殊なフォーマットのSQLコメントで、SQLオプティマイザに対する命令が含まれます。文レベルのオプティマイザ・ヒントは、適用対象となるSQL文の中に、次のいずれかの方法で適用できます。
/*+ */ ヒントは複数行にわたって定義できます。ヒントはコメント構文で囲む必要があります。プラス記号(+)はヒントの開始を示します。
--+ ヒントは1行で、プラス記号(+)の後に指定する必要があります。
文レベルのオプティマイザ・ヒントは、SELECT
、INSERT
、UPDATE
、MERGE
、DELETE
、CREATE TABLE AS SELECT
、またはINSERT ... SELECT
文の中に指定できます。SQL
VERB
のすぐ後で、コメント構文内にヒントを指定する必要があります。文レベルのオプティマイザ・ヒントの配置、ルールおよび構文の詳細は、『Oracle TimesTen In-Memory Database SQLリファレンス』の、文レベルのオプティマイザ・ヒントに関する説明に記載しています。
「トランザクションへのトランザクション・レベルのオプティマイザ・ヒントの適用」で説明する、TimesTenの組込みプロシージャによって定義されているトランザクション・レベルのオプティマイザ・ヒントは、SQL文の中で定義されたヒントで上書きされます。
注意: 文レベルのオプティマイザ・ヒントを誤って指定した場合、そのヒントはTimesTenによって無視され、エラーは発生しません。競合するヒントを定義すると、その文で競合するヒントは一番右のヒントによってすべて上書きされます。 |
トランザクション内のすべての文に対する問合せオプティマイザの動作を変更するには、ODBCプロシージャ・コール・インタフェースを使用して、アプリケーションで次の組込みプロシージャのいずれかをコールします。
注意: トランザクション・レベルのオプティマイザのヒントについて、自動コミットがオフになっていることを確認してください。オプティマイザのすべてのフラグは、トランザクションがコミットまたはロールバックされた時点でそれぞれのデフォルト値にリセットされます。自動コミットがオンになっている状態でオプティマイザ・フラグを設定しても、各文は固有のトランザクション内で実行されるため、そのフラグは無視されます。 |
ttOptSetFlag
: 特定のオプティマイザ・パラメータを設定します。トランザクション・レベルのオプティマイザ・ヒントを持つオプティマイザに、特定の問合せの最適化に関する推奨事項を提供します。
ttOptGetFlag
— データベースに設定されている既存のトランザクション・レベルのヒントを確認します。
ttOptUseIndex
: アプリケーションで、使用する索引の指定または特定の索引の使用の無効化をできるようにします。つまり、問合せの各相関について考慮する必要がある索引を指定します。
ttOptClearStats
、ttOptEstimateStats
、ttOptSetColIntvlStats
、ttOptSetTblStats
、ttOptUpdateStats
: TimesTen Data Managerでアプリケーションのデータに対して保持される統計を操作します。統計は、問合せオプティマイザによって様々な処理のコスト見積りに使用されます。
これらの組込みプロシージャの中には、ユーザーが実行対象のオブジェクトに対する権限を持っている必要のあるものがあります。これらの組込みプロシージャと必要な権限の詳細は、『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 */ ...