SQL問合せ実行計画の変更
問合せ計画を変更する必要がある場合、変更できるのはシステムPLAN
表に存在する問合せ計画のみです。
「システムPLAN表にある問合せ計画の表示」を参照してください。
問合せ計画を変更した場合、問合せ計画が置き換えられるのではなく、変更内容が含まれる新しい問合せ計画が作成されます。
次の項では、実行計画を変更する理由およびその変更方法について説明します。
実行計画を変更する理由
実行計画がアプリケーションに適していないかそのパフォーマンスが最適でない場合は、それを評価し変更します。
-
計画が、速度から見ると最適化されていても、アプリケーションには不適切なため。オプティマイザが最速の問合せ処理パスを選択しても、アプリケーション側から見れば、このパスが不適切な場合もあります。たとえば、オプティマイザが、特定の索引を選択すると、索引付けされた表で、更新や削除などの他の処理を同時に実行できなくなる場合があります。このような場合は、アプリケーションによって、これらの索引を使用できなくなる場合があります。
またオプティマイザが選択した計画で消費するメモリーが、実際の利用可能な容量より多かったり、アプリケーションで割り当てようとする容量より多い場合もあります。たとえば、計画で中間的な処理結果を保持したり、一時索引の作成が必要な場合に、このような容量不足が発生します。
-
計画のパフォーマンスが最適化されていないため。問合せオプティマイザは、表の内容、利用可能な索引、統計、様々な内部処理の相対的なコストを考慮して最速と考えられる計画を選択します。ただし、これらの情報を評価するとき、オプティマイザは予測やデータの一般化を行うことが多いため、最速の計画が選択されていない場合もあります。このような場合、よりよい計画を作成できるように、アプリケーションはオプティマイザの動作を調整できます。
ヒントは実行計画にどのように影響する可能性があるか
ヒントを適用して、TimesTen問合せオプティマイザに指示を渡すことができます。問合せに対して最適な実行計画を選択するとき、オプティマイザではこれらのヒントが考慮されます。
トランザクション・レベルのヒントは、トランザクション内のODBC SQLPrepare
関数またはJDBC PreparedStatement
オブジェクトへのすべてのコールに対して有効となります。
-
特定のヒントが有効な状態でコマンドが準備された場合、最初の準備トランザクション以外であっても、そのコマンドが自動的に再準備されたときはそのヒントが引き続き適用されます。これは、「問合せオプティマイザの使用による最適な計画の選択」で説明しているとおり、表の変更、索引の作成または破棄、あるいは統計の変更が実行されたときに起こる可能性があります。
-
ヒントなしでコマンドが準備された場合、そのコマンドは、自動的に再準備されても、その後のヒントに影響を受けることはありません。ヒントを有効にするには、アプリケーションでもう一度ODBC
SQLPrepare
関数またはJDBCConnection.prepareStatement()
メソッドをコールする必要があります。
ODBC使用時の結合のチューニング
開発者は、ODBCの使用時に結合をチューニングできます。
ODBCを使用する場合に開発者がT1
とT2
の結合を調整するには、次の図に示されているステップを実行することになります。
処理中は、アプリケーションで次の図に示されているステップが実行されます。
オプティマイザ・ヒントの使用による実行計画の変更
ヒントを適用して、TimesTen問合せオプティマイザに指示を渡すことができます。
-
特定のSQL文のみにヒントを適用するには、文レベルのオプティマイザ・ヒントを使用します。
-
トランザクション全体にヒントを適用するには、適切なTimesTen組込みプロシージャとともにトランザクション・レベルのオプティマイザ・ヒントを使用します。
-
TimesTen接続全体にヒントを適用するには、接続レベルのオプティマイザ・ヒントを使用します。
オプティマイザ・ヒントの優先順位は、文レベルのヒント、トランザクション・レベルのヒント、接続レベルのヒントとなります。
ノート:
TimesTenは読取り処理および書込み処理を同時に最適に処理します。ttOptSetFlag ('tblLock',1)
などのトランザクション・レベル・オプティマイザ・ヒントまたは/*+ tt_tbllock(1) tt_rowlock(0) */
などの文レベル・オプティマイザ・ヒントを使用すると、読取り専用同時実行性に対して読取り処理を最適化できます。読取り最適化処理と同時に処理する書込み処理は競合する可能性があります。
ttDbWriteConcurrencyModeSet
組込みプロシージャにより、同時書込み処理時に読取り最適化を制御できます。詳細は、「同時書込み処理時の読取り最適化の制御」を参照してください。
次の項では、ヒントの適用手順について説明します。
SQL文への文レベルのオプティマイザ・ヒントの適用
文レベルのオプティマイザ・ヒントは特殊なフォーマットのSQLコメントで、SQLオプティマイザに対する命令が含まれます。
文レベルのオプティマイザ・ヒントは、適用対象となるSQL文の中に、次のいずれかの方法で適用できます。
-
/*+ */ ヒントは複数行にわたって定義できます。ヒントはコメント構文で囲む必要があります。プラス記号(+)はヒントの開始を示します。
-
--+ ヒントは1行で、プラス記号(+)の後に指定する必要があります。
文レベルのオプティマイザ・ヒントは、SELECT
、INSERT
、UPDATE
、MERGE
、DELETE
、CREATE TABLE AS SELECT
またはINSERT ... SELECT
文の中に指定できます。SQL
VERB
のすぐ後で、コメント構文内にヒントを指定する必要があります。
文レベルのオプティマイザ・ヒントを誤って指定した場合、そのヒントはTimesTenによって無視され、エラーは発生しません。競合するヒントを定義すると、その文で競合するヒントは一番右のヒントによってすべて上書きされます。
文レベルのオプティマイザ・ヒントに固有の情報は、『Oracle TimesTen In-Memory Database SQLリファレンス』の文レベルのオプティマイザ・ヒントを参照してください。TimesTen Scaleout固有のオプティマイザ・ヒントについては、『Oracle TimesTen In-Memory Database Scaleoutユーザーズ・ガイド』のオプティマイザ・ヒントの使用を参照してください。
トランザクションへのトランザクション・レベルのオプティマイザ・ヒントの適用
トランザクション内のすべての文に対する問合せオプティマイザの動作を変更するには、アプリケーションで、ODBCプロシージャ・コール・インタフェースを使用してttOptSetFlag
組込みプロシージャをコールします。
ノート:
トランザクション・レベルのオプティマイザのヒントについて、自動コミットがオフになっていることを確認してください。オプティマイザのすべてのフラグは、トランザクションがコミットまたはロールバックされた時点でそれぞれのデフォルト値にリセットされます。自動コミットがオンになっている状態でオプティマイザ・フラグを設定しても、各文は固有のトランザクション内で実行されるため、そのフラグは無視されます。
-
ttOptSetFlag
—特定のオプティマイザ・パラメータを設定します。トランザクション・レベルのオプティマイザ・ヒントを持つオプティマイザに、特定の問合せの最適化に関する推奨事項を提供します。 -
ttOptGetFlag
— データベースに設定されている既存のトランザクション・レベルのヒントを確認します。 -
ttOptSetOrder
—アプリケーションで、表の結合順番を指定できるようにします。 -
ttOptUseIndex
—アプリケーションで、使用する索引の指定または特定の索引の使用の無効化をできるようにします。つまり、問合せの各相関について考慮する必要がある索引を指定します。 -
ttOptClearStats
、ttOptEstimateStats
、ttOptSetColIntvlStats
、ttOptSetTblStats
、ttOptUpdateStats
—TimesTenでアプリケーションのデータに対して保持される統計を操作します。統計は、問合せオプティマイザによって様々な処理のコスト見積りに使用されます。
これらの組込みプロシージャの中には、ユーザーが実行対象のオブジェクトに対する権限を持っている必要のあるものがあります。Oracle TimesTen In-Memory Databaseリファレンスの組込みプロシージャを参照してください。
次の例は、ttOptSetFlag
組込みプロシージャの使用方法を、ODBCとJDBCのそれぞれの場合について示しています。
ノート:
ttIsql
ユーティリティを使用して、オプティマイザの設定を試すこともできます。try
で始まるコマンドは、トランザクション・レベルのオプティマイザのヒントを制御します。現在のトランザクション・レベルのオプティマイザのヒント設定を確認するには、optprofile
コマンドを使用します。
例: 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(); } } . . . . . . . }
例: 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設定が上書きされます。
この例では、接続レベルのオプティマイザ・ヒントの使用方法を示しています。この例では、TT_RowLock
、TT_TblLock
およびTT_MergeJoin
を使用して、行ロックを有効にし、表ロックおよびマージ結合を無効にしています。/disk1/timesten
がtimesten_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) ...
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/timesten
がtimesten_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) ...
Oracle TimesTen In-Memory DatabaseリファレンスのOptimizerHintを参照してください。