ヘッダーをスキップ
Oracle® TimesTen In-Memory Databaseオペレーション・ガイド
11gリリース2 (11.2.2)
B66441-07
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

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

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

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

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

複数の実行計画が可能な場合、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 コマンドが再実行されます。
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つ以上のコマンドまたはその問合せ計画の詳細は、ttSQLCmdCacheInfoおよびttSQLCmdQueryPlan組込みプロシージャで表示できます。問合せ計画情報は、問合せの監視およびトラブルシューティングに使用します。

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

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

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

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

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

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.

SQL問合せ計画の表示

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

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

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

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

  2. 文の準備で、その文に対してODBC SSQLPrepare関数または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を使用して問合せおよびオプティマイザのヒントをテストできます。これにより計画生成が可能になるとともに、トランザクション内にある問合せ計画も示します。自動コミット・モードを無効にする必要があります。

autocommit 0;
showplan 1;

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

計画の生成を有効にしてコマンドの準備が終了すると、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表の各列の説明」を参照してください。

PLAN表の各列の説明

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

列1(ステップ)

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

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

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

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

列2(レベル)

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

jointree.gifの説明が続きます
jointree.gifの説明

列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は読取り問合せおよび書込み問合せを同時に最適に処理します。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の組込みプロシージャによって定義されているトランザクション・レベルのオプティマイザ・ヒントは、SQL文の中で定義されたヒントで上書きされます。


注意:

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

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

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


注意:

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

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

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

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

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

  • ttOptClearStatsttOptEstimateStatsttOptSetColIntvlStatsttOptSetTblStatsttOptUpdateStats: 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 */
...