SQLのチューニング

全体のロックおよびI/Oの方針の決定後、個々のSQL文をできるだけ効率的に実行できるようにしてください。

次の項では、SQL文を簡素化する方法について説明します。

文のチューニングと索引の使用

パフォーマンスへの影響: 大

すべての文が効率的に実行されているかどうかをチェックします。たとえば、使用する問合せは、必要な結果セットを生成するために必要な行のみを参照するようにします。

t1col1のみが必要であれば、次の文を使用します。

SELECT col1 FROM t1...

または、次を使用します。

SELECT * FROM t1...

TimesTenで文を実行するために使用される計画の表示方法については、TimesTen問合せオプティマイザを参照してください。また、計画は、ttIsql showplanコマンドを使用して表示することもできます。アプリケーションで頻繁に実行される各文の計画を表示します。索引が条件を評価するために使用されていない場合は、索引を使用できるように、新しい索引の作成または文や問合せの再作成を検討してください。たとえば、WHERE句の評価に索引を使用できるのは、比較条件(一致および不一致)の一方に単一の列が出現する場合か、BETWEEN条件内のみとなります。

この比較条件が頻繁に評価される場合は、再作成するのが妥当です。

WHERE c1+10 < c2+20

次のようにします。

WHERE c1 < c2+10

c1に索引を作成します。

索引が存在することにより、UPDATEINSERTDELETECREATE VIEWなどの書込み操作の処理速度が遅くなります。アプリケーションでの読取りが少ないものの、表への書込みが多い場合は、その表の索引によってパフォーマンスが向上するのではなく、低下する可能性があります。

場合によっては、問合せ評価の処理速度を向上するために、システムによって一時索引が作成される場合があります。このような場合が頻繁にある場合は、アプリケーション自体で索引を作成する方が効率的です。MONITOR表のCMD_TEMP_INDEXES列は、問合せ評価時に一時索引が作成された回数を示します。

表またはキャッシュ・グループに対して時間ベースのエージングを実装している場合は、タイムスタンプ列に索引を作成すると、エージングのパフォーマンスが向上します。「時間ベースのエージング」を参照してください。

SQL文実行時間のサンプリングの収集および評価

パフォーマンスへの影響: 不定

TimesTenには、SQL操作のランタイムを測定することでSQL文のパフォーマンスを判断できる組込みプロシージャがあります。

追跡のかわりに、組込みプロシージャがSQL文の処理中にランタイムをサンプリングします。この組込みプロシージャは、SQLExecute API内で処理の時間を測定することで、SQL文のランタイムを測定します。

ttStatsConfig組込みプロシージャと次の名前と値のペアを使用して、サンプリング・レートとランタイムの収集方法を構成できます。

ノート:

Oracle TimesTen In-Memory DatabaseリファレンスttStatsConfigを参照してください。

表10-1 ttStatsConfigのパラメータと値の説明

パラメータ 説明

SQLCmdSampleFactor

SQL文のランタイム・サンプルを収集する頻度を構成します。デフォルトは0です。これはサンプリングをオフにするという意味です。たとえば10に設定すると、TimesTenはSQL文のランタイムのウォール・クロック時間を、10個の文ごとにキャプチャします。

ConnSampleFactor

個々の接続でSQL文のサンプルを収集する頻度を構成します。値は2個のパラメータがカンマで区切られ、引用符で囲まれているため、単一の値のように見えます。1番目の値は接続IDです。2番目の値はSQLCmdSampleFactorと同じで、コマンドのサンプルを取得する頻度を指定する数値です。デフォルトでは、個々の接続に対してサンプリングはオフになっています(0に設定されています)。

SQLCmdHistogramReset

0以外の値に設定すると、SQLランタイムのヒストグラム・データがクリアされます。

StatsLevel

使用する統計レベルを設定します。値はNONEBASICTYPICAL、またはALLに設定できます。デフォルトはTYPICALです。レベルをALLに設定すると、パフォーマンスが低下する場合があります。

次は、ttStatsConfig組込みプロシージャで名前と値のペアを設定する方法の例です。

ノート:

すべてのトランザクションをサンプリングするかわりに、ttStatsConfig組込みプロシージャのConnSampleFactorパラメータを使用して代表的な接続を選択すると、最良の結果が得られます。小さなサンプリング係数ですべてのトランザクションをサンプリングすると、パフォーマンスが低下するおそれがあります。

意味のある結果を得るには、データベースをメモリーに読み込んだままにする必要があります。データベースのアンロードとリロードを行うと、SQLコマンドキャッシュが空になるためです。

接続1で文を5個ごとにサンプリングします。

Command> call ttStatsConfig('ConnSampleFactor', '1,5');
< CONNSAMPLEFACTOR, 1,5 >
1 row found.

接続1のサンプリングをオフにします。

Command> call ttStatsConfig('ConnSampleFactor', '1,0');
< CONNSAMPLEFACTOR, 1,0 >
1 row found.

すべてのコマンドをサンプリングします:

Command> call ttStatsConfig('SqlCmdSampleFactor',1);
< SQLCMDSAMPLEFACTOR, 1 >
1 row found.

サンプリングの有無を確認します:

Command> call ttStatsConfig('SqlCmdSampleFactor');
< SQLCMDSAMPLEFACTOR, 1 >
1 row found.

データベース統計の現在の収集レベルを確認します。

Command> call ttStatsConfig('StatsLevel');
< STATSLEVEL, TYPICAL >
1 row found.

データベース統計収集をNONEに設定してオフにします。

Command> call ttStatsConfig('StatsLevel','None');
< STATSLEVEL, NONE >
1 row found.

収集する統計の構成の完了後、ttSQLCmdCacheInfo組込みプロシージャを使用すると、収集された統計が表示されます。ランタイム・ヒストグラムをコマンド・レベルまたはデータベース・レベルで表示するには、ttSQLExecutionTimeHistogram組込みプロシージャを使用します。

ttSQLCmdCacheInfo組込みプロシージャは、SQLランタイム統計に関する次の情報を表示します。

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

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

  • この文の最大ウォール・クロック・ランタイムが秒単位で表示されます。

  • 最後に測定されたランタイムが秒単位で表示されます。

  • 最小ランタイムが秒単位で表示されます。

次の例では、ディスプレイには末尾の5つの値に次の統計が表示されます。

Command> vertical call ttSQLCmdCacheInfo(135680792);

  SQLCMDID:                        135680792
  PRIVATE_COMMAND_CONNECTION_ID:   -1
  EXECUTIONS:                      97414
  PREPARES:                        50080
  REPREPARES:                      1
  FREEABLE:                        1
  SIZE:                            3880
  OWNER:                           SALES
  QUERYTEXT:                       select min(unique2) from big1
  FETCHCOUNT:                      40
  STARTTIME:                       2018-04-10 13:10:46.808000
  MAXEXECUTETIME:                  .001319
  LASTEXECUTETIME:                 .000018
  MINEXECUTETIME:                  .000017
  EXECLOC:                         0
  GRIDCMDID:                       00000000000000000000  TEMPSPACEUSAGE:                  0  MAXTEMPSPACEUSAGE:               0
1 row found.

Oracle TimesTen In-Memory DatabaseリファレンスttSQLCmdCacheInfoを参照してください。

ttSQLExecutionTimeHistogram組込みプロシージャは、SQLランタイムのヒストグラムを、単一のSQLコマンドまたはコマンド・キャッシュにあるすべてのSQLコマンドに対して表示します。その際、サンプリングが有効になっていると仮定されます(SQLCmdSampleFactorが0より大きい)。

ヒストグラムには、ヒストグラムのバケットごとに1つの行が表示されます。各行には次の情報が含まれます。

  • TimesTenデータベースを開始した時点、またはttStatsConfig組込みプロシージャを使用して統計をリセットした時点のいずれか以降に測定された、SQL文のランタイム操作の数。

  • 累積ウォール・クロック・ランタイム。

  • 各タイムフレームを示すランタイム制限。

  • 最後の行は、特定のタイムフレーム内に実行されたSQL文の数を示します。

次の例は、ttSQLExecutionTimeHistogram組込みプロシージャの出力を示します。

次のttSQLExecutionTimeHistogram組込みプロシージャの例は、合計1919個の文が実行されたことを示します。1919個の文すべての合計実行時間は1.090751秒でした。この例は、SQL文が次のタイムフレーム内で実行されたことを示します。

  • 0.00001562秒以下のタイムフレーム内で、278個の文が実行されました。

  • 0.00001562秒より大きく0.000125秒以下のタイムフレームで、1484個の文が実行されました。

  • 0.000125秒より大きく0.001秒以下のタイムフレームで、35個の文が実行されました。

  • 0.001秒より大きく0.008秒以下のタイムフレームで、62個の文が実行されました。

  • 0.008秒より大きく0.064秒以下のタイムフレームで、60個の文が実行されました。

Command> call ttSQLExecutionTimeHistogram;
< 1919, 1.090751, .00001562, 278 >
< 1919, 1.090751, .000125, 1484 >
< 1919, 1.090751, .001, 35 >
< 1919, 1.090751, .008, 62 >
< 1919, 1.090751, .064, 60 >
< 1919, 1.090751, .512, 0 >
< 1919, 1.090751, 4.096, 0 >
< 1919, 1.090751, 32.768, 0 >
< 1919, 1.090751, 262.144, 0 >
< 1919, 1.090751, 9.999999999E+125, 0 >
10 rows found.

データ・ロード時のパフォーマンスのための索引のない表の作成

パフォーマンスへの影響: 不定

データを含む表のロードを計画している場合は、索引を使用しない表の作成を検討してください。

データのロード後に、索引を作成できます。これにより、データを表にロードするのにかかる時間が短縮されます。例外は、外部キーおよび参照表を使用している場合です。

適切なタイプの索引の選択

パフォーマンスへの影響: 不定

TimesTenデータベースでは、ハッシュ索引と範囲索引がサポートされています。

次に、それぞれの索引の種類をいつ使用するのが適切か説明します。

ハッシュ索引は、1つ以上の列で完全一致する行を検索する場合に有効です。ハッシュ索引は、一致検索の実行に便利です。ハッシュ索引は次のいずれかの方法で作成されます。

  • CREATE [UNIQUE] HASH INDEX文を使用すると、ハッシュ索引または一意のハッシュ索引を作成できます。

  • CREATE TABLE... UNIQUE HASH ON文を使用すると、表の作成時に一意のハッシュ索引を作成できます。一意のハッシュ索引は、表の主キー列に対して指定します。

    ノート:

    データを含む表のロードを計画している場合は、索引を使用しない表の作成を検討してください。データのロード後に、索引を作成できます。これにより、データを表にロードするのにかかる時間が短縮されます。例外は、外部キーおよび参照表を使用している場合です。

範囲索引は、デフォルトではCREATE TABLE文で作成します(CREATE [UNIQUE] HASH INDEX文で作成することも可能です)。範囲索引では完全一致のキーの検索を高速化でき、より柔軟性が高く、他の問合せの高速化にも利用できます。問合せにLESS THANまたはGREATER THANの比較がある場合は、範囲索引を選択します。範囲索引は、カーディナリティの高いデータ(CUSTOMER_NAMEまたはPHONE_NUMBERなどの使用可能な値が多数あるデータ)に対して効果的です。範囲索引はインメモリーのデータ管理に最適化されています。

また、範囲索引は、接頭辞問合せの高速化に使用することもできます。接頭辞問合せでは、指定されている最後のキー列以外のすべての列に一致条件を指定できます。接頭辞問合せの最後の列には、一致条件または不一致条件を指定できます。

次の表および索引の定義について考えてみます。

Command> CREATE TABLE T(i1 tt_integer, i2 tt_integer, i3 tt_integer, ...);
Command> CREATE INDEX IXT on T(i1, i2, i3);

索引IXTを使用すると、次の問合せを高速化できます。

Command> SELECT * FROM T WHERE i1>12;
Command> SELECT * FROM T WHERE i1=12 and i2=75;
Command> SELECT * FROM T WHERE i1=12 and i2 BETWEEN 10 and 20;
Command> SELECT * FROM T WHERE i1=12 and i2=75 and i3>30;

索引IXTは次の問合せには使用されません。接頭辞プロパティが条件を満たしていないためです。

Command> SELECT * FROM T WHERE i2=12;

i1に一致条件が指定されていません。

次のような問合せの場合、索引IXTは使用されますが、一致検索は最初の2列のみに対して実行されます。

Command> SELECT * FROM T WHERE i1=12 and i2<50 and i3=630;

範囲索引の構造は、表サイズの変更に対応して自動的に調整される動的構造です。範囲索引は、一意にすることも一意にしないこともでき、またNULL値可能列に対して宣言することもできます。また、レコードの挿入後、索引付けされた列の値を変更することもできます。範囲索引は、ほとんどの場合、同等のハッシュ索引より単純です。

ハッシュ索引サイズの適切な設定

パフォーマンスへの影響: 不定

TimesTenはハッシュ索引を、主キーの制約として、およびCREATE INDEX文の一部として指定された場合の両方で使用します。ハッシュ索引のサイズは、CREATE TABLEおよびCREATE INDEX文のUNIQUE HASH ON句で指定するPAGESパラメータで決まります。

PAGESの値は、表の予想行数を256で除算した値にします。たとえば、256,000行の表の場合、PAGES = 1000とします。小さい値を指定すると、ハッシュ競合の数が増加してパフォーマンスが低下し、大きい値を指定すると、パフォーマンスが多少向上するかわりに索引で追加の領域が必要になります。

表の行数が大幅に変動し、パフォーマンスが主な検討事項である場合、大きな索引を作成するのが最善です。表のサイズを正確に予測できない場合は、範囲索引を使用することを検討してください。また、索引付けする列が大きいCHAR値またはバイナリ値の場合、あるいは索引付けする列が多い場合は、一意索引の使用を検討してください。これらの場合は、一意索引の方がハッシュ索引より高速になる場合があります。

表のサイズが大きくなるにつれてレコード挿入のパフォーマンスが低下する場合は、表の予想サイズを小さく見積りすぎていた可能性があります。ALTER TABLE文を使用してUNIQUE HASH ON句のPAGES値を再設定することによって、ハッシュ索引のサイズを変更できます。SET PAGESについては、『Oracle TimesTen In-Memory Database SQLリファレンス』ALTER TABLEの項を参照してください。

外部キー制約の適切な使用

パフォーマンスへの影響: 不定

外部キーを宣言しても、SELECT問合せのパフォーマンスには影響ありませんが、外部キーが定義された表でINSERTおよびUPDATE操作を実行する場合、および外部キーで参照される表でUPDATEおよびDELETE操作を実行する場合は、パフォーマンスが低下します。

この低下は、表を参照する外部キーの数または表に定義されている外部キーの数に比例します。

正確な統計または見積り統計の計算

パフォーマンスへの影響: 大

データベース内のデータに関する統計が利用できる場合、TimesTenオプティマイザは、コマンドを準備する際に、それらの統計を使用してデータへの最適なパスを決定します。統計がない場合、オプティマイザは、データ配布に関して一般的な予測を行います。

ノート:

TimesTen問合せオプティマイザを参照してください。

情報によって問合せオプティマイザの計画がより効率的になる可能性があるため、文を準備する前に統計を計算する必要があります。パフォーマンスは統計収集プロセスの影響を受けるため、統計を収集する場合は、新しい統計を収集するとき、およびその頻度を決定する必要があります。収集の頻度は、統計収集プロセスで起こるオーバーヘッドの処理に対し、オプティマイザの正確な統計を出すタスクのバランスをとる必要があります。

統計の計算は時間がかかる処理のため、次のガイドラインを使用して統計を計算してください。

  • データベースのロード後またはアプリケーションのメジャー・アップグレード後に、統計を更新します。

  • トランザクションのロードが大きいときに統計を更新しないでください。

  • 表、列またはPL/SQLオブジェクトに相当な作成および変更がある場合は、統計を更新します。

    データベースで相当数の表、列またはPL/SQLオブジェクトを作成または変更した場合、システム表SYS.TABLESSYS.COLUMNSおよびSYS.OBJ$に対応したデータ・ディクショナリのオプティマイザ統計を更新する必要があります。

  • バルク・ロードや一括削除など、バッチ操作で表を大幅に変更する場合、バッチ操作の一環としてこれらの表の統計を収集できます。

  • 表が増分的に変更されるだけの場合は、1週間に1回や1か月に1回程度の頻度で、統計を更新します。

  • トランザクション負荷が低い時間帯は、定期的に実行されるスクリプトまたはバッチ・ジョブの一環として統計を更新します。

  • 複数の大規模な表について統計を更新する場合は、「大規模な表の表統計のパラレルでの更新」を参照してください。

ノート:

パフォーマンス上の理由から、TimesTenでは、統計が計算される際に表または行のロックは保持されません。

統計を計算するために、ttIsql statsupdateコマンド、ttOptUpdateStatsまたはttOptEstimateStatsを使用します。表名として空の文字列を指定すると、現行ユーザーのスキーマ内のすべての表の統計が更新されます。

  • ttIsql内のstatsupdateコマンドは、対象の表の各行を評価し、正確な統計を計算します。

  • ttOptUpdateStats組込みプロシージャは、対象となる表のすべての行を評価し、正確な統計を計算します。

  • ttOptEstimateStats組込みプロシージャは、対象となる表の一部の行のみを評価し、見積り統計を計算します。これは高速に実行できますが、統計の正確性に劣ることがあります。10パーセントのサンプルで統計を計算すると、正確な統計を計算するより処理が約10倍速くなり、通常は同じ実行計画が生成されます。

ノート:

『Oracle TimesTen In-Memory Databaseリファレンス』ttIsqlおよび組込みプロシージャを参照してください。

大規模な表の表統計のパラレルでの更新

パフォーマンスへの影響: 大

すべてのTimesTen表で表統計を最新の状態に保つことは重要です。ただし、この処理を大規模な表で実行すると、時間がかかり、パフォーマンスに負荷がかかります。複数の大規模な表の統計を更新する場合は、ttOptUpdateStats組込みプロシージャをパラレルでコールすることを検討してください。

ノート:

100万行より少ない行が含まれている場合、TimesTen表は小規模な表とみなされます。1億行を超える行が含まれている場合、TimesTen表は大規模な表とみなされます。

表統計を更新する場合は、すべての大規模な表に対してttOptUpdateStats組込みプロシージャをコールします。それぞれのttOptUpdateStats組込みプロシージャをパラレルでコールしてください。Oracle TimesTen In-Memory DatabaseリファレンスttOptUpdateStatsを参照してください。

Command> call ttOptUpdateStats('table1',0,0);
Command> call ttOptUpdateStats('table2',0,0);
...
...
Command> call ttOptUpdateStats('finaltable',0,0);

ttOptUpdateStats組込みプロシージャのコールが完了したら、表統計を更新した大規模なTimesTen表に対するトランザクションのアクセス数を確認します。トランザクション・ロード時間が短い間はttOptCmdCacheInvalidate('',1)組込みプロシージャを実行します。Oracle TimesTen In-Memory DatabaseリファレンスttOptCmdCacheInvalidateを参照してください。トランザクション・ロード時間が長いときに、次の組込みプロシージャを実行し、各ttOptCmdCacheInvalidate組込みプロシージャはパラレルでコールします。

Command> call ttOptCmdCacheInvalidate('table1',1);
Command> call ttOptCmdCacheInvalidate('table2',1);
...
...
Command> call ttOptCmdCacheInvalidate('finaltable',1);

表の表統計が更新され、SQLコマンド・キャッシュのコンパイルされたコマンドは無効になりました。

現在の表統計を再生成するスクリプトの作成

パフォーマンスへの影響: 不定

表統計を現在の状態にリストアできるttOptStatsExport組込みプロシージャを使用して、SQLスクリプトを生成できます。

これらの文を適用する場合、同じ環境を再作成します。表統計の再作成は、SQLパフォーマンスの診断に使用できます。

ttOptStatsExport組込みプロシージャをコールして、表統計を現在の状態にリストアするために必要な一連の文を返します。表を指定しない場合、ttOptStatsExportは、コール元のユーザーがアクセス権限を持っているすべてのユーザー表についての表統計をリストアするために必要な一連の文を返します。

ノート:

Oracle TimesTen In-Memory DatabaseリファレンスttOptStatsExportを参照してください。

次の例では、employees表の統計をリストアするための実行に必要な一連の組込みプロシージャ・コマンドを返します。

Command> call ttOptStatsExport('hr.employees');

< call ttoptsetcolIntvlstats('HR.EMPLOYEES', 'EMPLOYEE_ID', 0, (6, 0, 107, 107,
 (20, 20, 1 ,100, 120, 101), (20, 20, 1 ,121, 141, 122), (20, 20, 1 ,142, 162, 
143), (20, 20, 1 ,163, 183, 164), (20, 20, 1 ,184, 204, 185), (1, 1, 1 ,205, 206, 
205))); >
< call ttoptsetcolIntvlstats('HR.EMPLOYEES', 'FIRST_NAME', 0, (1, 0, 89, 107, 
(89, 107, 0, 'Adam', 'Winston', 'Adam'))); >
< call ttoptsetcolIntvlstats('HR.EMPLOYEES', 'LAST_NAME', 0, (1, 0, 97, 107, (97, 
107, 0, 'Abel', 'Zlotkey', 'Abel'))); >
< call ttoptsetcolIntvlstats('HR.EMPLOYEES', 'EMAIL', 0, (6, 0, 107, 107, (20, 
20, 1, 'ABANDA', 'DGREENE', 'ABULL'), (20, 20, 1, 'DLEE', 'JKING', 'DLORENTZ'), 
(20, 20, 1, 'JLANDRY', 'LOZER', 'JLIVINGS'), (20, 20, 1, 'LPOPP', 'RMATOS', 
'LSMITH'), (20, 20, 1, 'RPERKINS', 'WGIETZ', 'SANDE'), (1, 1, 1, 'WSMITH', 
'WTAYLOR', 'WSMITH'))); >
< call ttoptsetcolIntvlstats('HR.EMPLOYEES', 'PHONE_NUMBER', 0, (1, 0, 103, 107, 
(103, 107, 0, '011.44.1343.329268', '650.509.4876', '011.44.1343.329268'))); >
< call ttoptsetcolIntvlstats('HR.EMPLOYEES', 'HIRE_DATE', 0, (1, 0, 90, 107, (90, 
107, 0 ,'1987-06-17 00:00:00', '2000-04-21 00:00:00', '1987-06-17 00:00:00'))); >
< call ttoptsetcolIntvlstats('HR.EMPLOYEES', 'JOB_ID', 0, (4, 0, 19, 107, (11, 
16, 5, 'AC_ACCOUNT', 'PR_REP', 'FI_ACCOUNT'), (3, 11, 30, 'PU_CLERK', 'SA_REP', 
'SA_REP'), (1, 20, 20, 'SH_CLERK', 'ST_CLERK', 'ST_CLERK'), (0, 0, 5, 'ST_MAN', 
'ST_MAN', 'ST_MAN'))); >
< call ttoptsetcolIntvlstats('HR.EMPLOYEES', 'SALARY', 0, (1, 0, 57, 107, (57, 
107, 0 ,2100, 24000, 2100))); >
< call ttoptsetcolIntvlstats('HR.EMPLOYEES', 'COMMISSION_PCT', 0, (1, 72, 7, 107, 
(7, 35, 0 ,0.1, 0.4, 0.1))); >
< call ttoptsetcolIntvlstats('HR.EMPLOYEES', 'MANAGER_ID', 0, (1, 1, 18, 107, 
(18, 106, 0 ,100, 205, 100))); >
< call ttoptsetcolIntvlstats('HR.EMPLOYEES', 'DEPARTMENT_ID', 0, (3, 1, 11, 107, 
(4, 10, 45 ,10, 50, 50), (2, 6, 34 ,60, 80, 80), (2, 5, 6 ,90, 110, 100))); >
< call ttoptsettblstats('HR.EMPLOYEES', 107, 0); >
12 rows found.

SQLコマンド・キャッシュ内のコマンドの無効化の制御

パフォーマンスへの影響: 不定

TimesTenは、コンパイルされたコマンドをSQLコマンド・キャッシュにキャッシュします。これらのコマンドは無効化できます。無効化されたコマンドは、通常は、再実行される直前に自動的に再準備されます。1つのコマンドが何度も準備されることがあります。

ノート:

コマンドがどのように自動的に無効になるかの詳細は、「問合せオプティマイザの使用による最適な計画の選択」を参照してください。

統計を計算するとき、特定の表にある同一のロックについて、コマンドの更新とコンパイルのプロセスが競合することがあります。複数のトランザクションで統計を収集していて、統計の更新ごとにコマンドを無効にしていると、次の問題が発生することがあります。

  • 複数の表を参照する結合問合せが無効化され、2回以上再コンパイルされることがあります。

  • 再コンパイルに必要なロックが統計の更新に差し支え、その結果デッドロックが発生することがあります。

これらの問題を回避するには、コマンドがSQLコマンド・キャッシュで無効化されるタイミングを制御します。さらに、表と索引の基数が今後大幅に変更されることがわかっている場合には、すべてのコマンドの無効化を延期することも考えられます。

コマンドの無効化は次のように制御できます。

  1. SQLコマンド・キャッシュでコマンドを無効化せずに、統計を計算します。ttIsql statsupdateコマンド、ttOptUpdateStats組込みプロシージャまたはttOptEstimateStats組込みプロシージャで、invalidateオプションを0に設定します。

  2. すべての統計がttOptCmdCacheInvalidate組込みプロシージャでコンパイルされたら、SQLコマンド・キャッシュ内でコマンドを手動で無効にします。

ttOptCmdCacheInvalidate組込みプロシージャを使用すると、ある表のみに関連付けられたコマンドや、SQLコマンド・キャッシュ内にあるすべてのコマンドを無効化できます。さらに、無効化したコマンドを再コンパイルするか、使用不可としてマークするかを指定できます。

ノート:

統計を最適に計算するタイミングの詳細は、「正確な統計または見積り統計の計算」を参照してください。また、『Oracle TimesTen In-Memory Databaseリファレンス』ttIsqlttOptUpdateStatsttOptEstimateStatsまたはttOptCmdCacheInvalidateを参照してください。

ALTER TABLEの回避

パフォーマンスへの影響: 不定

ALTER TABLE文を使用すると、アプリケーションで表に対して列の追加および破棄を実行できます。ALTER TABLE文自体は、ほとんどの場合、非常に高速に実行できますが、これによって表に加えられた変更が原因で、表の後続のDML文および問合せの実行に時間がかかることがあります。

アプリケーションで発生する実際のパフォーマンスの低下の程度は、表の変更回数および表に対して実行される処理の種類によって異なります。

VARCHAR2列およびVARBINARY列の削除は、削除対象の列内の既存のVARCHAR2値およびVARBINARY値に割り当てられている領域を解放するために、表をスキャンする必要があるため、他のデータ型の列の削除より時間がかかります。

問合せのネストの回避

パフォーマンスへの影響: 不定

多くの行の実体化が必要な問合せのネストを回避するため、可能でばれば問合せをリライトすることをお薦めします。

次のネストした問合せの例では、実体化が必要になり、多くの行が作成される場合があります。

  • GROUP BYを使用するネストした集合問合せ

  • ROWNUMを参照するネストした問合せ

  • UNION、INTERSECTまたはMINUSを使用するネストした問合せ

  • ORDER BYを使用するネストした問合せ

たとえば、次のネストした集合問合せによって、パフォーマンスに大きく影響します。

Command> SELECT * FROM (SELECT SUM(x1) sum1 FROM t1 GROUP BY y1), 
(SELECT sum(x2) sum2 FROM t2 GROUP BY y2) WHERE sum1=sum2;

次に、ROWNUMを参照するネストした問合せの例を示します。

Command> SELECT * FROM (SELECT rownum rc, x1 FROM t1 WHERE x1>100), 
(SELECT ROWNUM rc, x2 FROM t2 WHERE x2>100) WHERE x1=x2;

次に、UNIONを使用するネストした問合せの例を示します。

Command> SELECT * FROM (SELECT x1 FROM t1 UNION SELECT x2 FROM t2), 
(SELECT x3 FROM t3 GROUP BY x3) WHERE x1=x3;

Oracle TimesTen In-Memory Database SQLリファレンス副問合せを参照してください。

文の事前準備

パフォーマンスへの影響: 大

同じ文を複数回生成し、その生成のたびに異なる値を検索するアプリケーションが存在する場合は、パラメータ化した文を準備して、コンパイル時間を短縮します。

たとえば、アプリケーションで次のような文が生成されるとします。

SELECT A FROM B WHERE C = 10;
SELECT A FROM B WHERE C = 15;

これらの文は、次の単一の文に置き換えることができます。

SELECT A FROM B WHERE C = ?;

TimesTenでは、準備済の文はコミットされると自動的に共有されます。したがって、文の実行を準備するためのアプリケーションによるリクエストは、その文の準備済バージョンがすでにシステムに存在する場合は非常に高速に処理されます。また、同じ文を実行するリクエストを繰り返し行う場合は、その文の事前準備済バージョンを共有することによって、準備でのオーバーヘッドを回避できます。

TimesTenで準備済の文を共有できる場合でも、パフォーマンス上の理由から、パラメータ化した文を使用することをお薦めします。パラメータ化した文を使用すると、文の共有による軽減に加えて、準備でのオーバーヘッドをさらに軽減することができます。

不要な準備処理の回避

パフォーマンスへの影響: 大

SQL文の準備は高コストの処理であるため、アプリケーションでは準備APIのコール回数を最小限にする必要があります。ほとんどのアプリケーションでは、接続の開始時に一連の文を準備し、接続中にこれらの文を使用します。この方法は、数百または数千のトランザクションで構成されている長時間の接続に適しています。

ただし、接続が比較的短時間の場合でも、すべてのスレッドまたはプロセスのために文を準備して実行する長時間の接続を確立することをお薦めします。この場合、通信でのオーバーヘッドと準備でのオーバーヘッドのバランスを考慮する必要があり、アプリケーションごとに調べることができます。準備済の文は、接続がクローズされると無効になります。

『Oracle TimesTen In-Memory Databaseリファレンス』ttSQLCmdCacheInfoGetを参照してください。

表の列ベース圧縮によるデータの効率的な格納

パフォーマンスへの影響: 大

TimesTenには、パフォーマンスは低下しますが、データをより効率的に保存する、列レベルでの表圧縮機能があります。

この仕組みでは、列の値の重複による表内の冗長な領域が排除され、表の領域が削減されるので、全表スキャンを実行するSQL問合せのパフォーマンスが向上します。

TimesTen表の列を圧縮する場合は、次の点を考慮してください。

  • 国または州の名前などの全体にわたって値が繰り返されている場合は、列を圧縮します。

  • 複数の列に同時に頻繁にアクセスする場合は、列を圧縮します。

  • TT_TINYINTなどの少量の記憶域を必要とするデータ型を含む列は圧縮しません。

  • TimesTenはNULL値を圧縮しません。

表の圧縮される1つ以上の列(圧縮列グループと呼ばれる)を定義できます。各表に1つ以上の圧縮列グループを定義できます。

各圧縮列グループに対して、圧縮列グループのすべての個別値の列を含むディクショナリ表が作成されます。圧縮列グループには、ディクショナリ表の適切な値の行へのポインタが含まれます。このポインタの幅は、ディクショナリ表に対して定義した最大エントリ数に応じて、1、2または4バイトです。そのため、圧縮されている列グループ内の列の幅の合計が、1、2または4バイトのポインタの幅より広い場合、およびこれらの列値に多くの重複する値が存在する場合は、表で使用される領域を削減しました。

図10-1に、ディクショナリ表内の適切な行を指す、表内の圧縮列グループを示します。

図10-1 表の列ベース圧縮

図10-1の説明が続きます
「図10-1 表の列ベース圧縮」の説明

ディクショナリ表には、各個別値へのポインタの列があります。ユーザーが圧縮列グループの個別エントリの最大数を構成すると、圧縮列グループのサイズが次のように設定されます。

  • エントリの最大数が255(28-1)の場合は1バイト。最大数が1から255の場合、ディクショナリのサイズは255(28-1)に設定され、圧縮列グループのポインタ列は1バイトになります。

  • エントリの最大数が65,535(216-1)の場合は2バイト。最大数が256から65,535の場合、ディクショナリのサイズは65,535(216-1)に設定され、圧縮列グループのポインタ列は2バイトになります。

  • エントリの最大数が4,294,967,295(232-1)の場合は4バイト。最大数が65,536から4,294,967,295の場合、ディクショナリのサイズは4,294,967,295(232-1)に設定され、圧縮列グループのポインタ列は4バイトになります。これがデフォルトです。

圧縮列グループは、表の作成時に追加するか、ALTER TABLE文を使用して後で追加できます。ALTER TABLE文を使用して、圧縮列グループ全体を削除できます。『Oracle TimesTen In-Memory Database SQLリファレンス』ALTER TABLEおよびCREATE TABLEを参照してください。

ttSize組込みプロシージャをコールして、TimesTenが圧縮された表に対して実行した圧縮のレベルを確認できます。ttSize組込みプロシージャの詳細は、『Oracle TimesTen In-Memory Databaseリファレンス』ttSizeを参照してください。

同時書込み処理時の読取り最適化の制御

パフォーマンスへの影響: 不定

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

読取り最適化問合せと同時に処理する書込み処理は競合する可能性があります。

ttDBWriteConcurrencyModeSet組込みプロシージャにより、同時書込み処理時に読取り最適化を制御できます。この組込みプロシージャにより、標準モードと拡張書込み同時モードを切り替えることができます。標準モードでは、オプティマイザは読取り最適化のヒントを考慮します。拡張書込み同時モードでは、オプティマイザは読取り最適化のヒントを無視し、共有の読込み表ロックまたは書込み表ロックを使用しません。

ノート:

表ロックの詳細は、「ロックの粒度」を参照してください。

オプティマイザ・ヒントの詳細は、「オプティマイザ・ヒントの使用による実行計画の変更」を参照してください。

トランザクション・レベル・オプティマイザ・ヒントの詳細は、『Oracle TimesTen In-Memory Databaseリファレンス』ttOptSetFlagを参照してください。

ttDBWriteConcurrencyModeSet組込みプロシージャのmode1に設定して、拡張書込み同時モードを有効にし、読取り最適化を無効にします。mode0に設定して、拡張書込み同時モードを無効にし、読取り最適化を再有効化します。

mode1に設定すると、すべてのトランザクションおよび文の表ロック・オプティマイザ・ヒントが無視されます。これは次に影響します。

  • SELECT問合せの共有読取り表レベル・ロックおよびオプティマイザ・ヒントでトリガーされる副問合せ。

  • オプティマイザ・ヒントでトリガーされるDML文の書込み表ロック。

modeの設定にかかわらず、オプティマイザ・ヒントでトリガーされない表ロックは影響を受けません。

ttDBWriteConcurrencyModeSet組込みプロシージャのwait0に設定して、通知せずにモード切替えを実行します。ttDBWriteConcurrencyModeSet組込みプロシージャのwait1に設定して、モード切替えが完了するまで組込みプロシージャが待機するように強制します。

特定のSQL文を実行するとttDBWriteConcurrencyModeSet組込みプロシージャのモードが移行中のままになります。このようなSQL文は次の2つの条件に一致します。

  • 書込み同時実行モードの影響を受ける場合。

  • 異なる書込み同時実行モードでコンパイルされた場合。

ttDBWriteConcurrencyModeSet組込みプロシージャのモードは、このようなSQL文がすべて完了するまで移行中のままになります。ttDBWriteConcurrencyModeSet組込みプロシージャは、モード移行時にロック取得を使用して待機します。ttDBWriteConcurrencyModeSet組込みプロシージャが現在の接続のタイムアウト時間内にロックを許可されない場合、エラーが返されます。

ノート:

『Oracle TimesTen In-Memory Databaseリファレンス』ttDBWriteConcurrencyModeSetttLockWaitおよびttDBWriteConcurrencyModeGetを参照してください。

SQLおよびPL/SQLのタイムアウト値の選択

パフォーマンスへの影響: 不定

タイムアウト値を設定するときは、特定の接続属性の間の関係を考慮する必要があります。
  • SQLQueryTimeoutまたはSQLQueryTimeoutMSec: SQL文がタイムアウトする前に実行される時間の長さを制御します。

    デフォルトでは、SQL文はタイムアウトしません。場合によっては、SQLQueryTimeoutまたはSQLQueryTimeoutMSec接続属性の値を指定して、時間制限を秒またはミリ秒単位で設定し、この制限内でデータベースのSQL文が実行されるようにできます。(これは、問合せだけでなく、すべてのSQL文に適用されることに注意してください。)

    SQLQueryTimeoutおよびSQLQueryTimeoutMsec属性はどちらも、1つのタイムアウト値(ミリ秒)に内部的にマップされます。これらの属性に異なる値が指定された場合は、1つの値のみが保持されます。『Oracle TimesTen In-Memory Databaseリファレンス』SQLQueryTimeoutおよびSQLQueryTimeoutMSecを参照してください。

  • PLSQL_TIMEOUT: PL/SQLブロックがタイムアウトする前に実行される時間の長さを制御します。

    デフォルトでは、PL/SQLプログラム・ユニット(PL/SQLプロシージャ、無名ブロックおよび関数)は、自動的に終了されるまで30秒間実行できます。場合によっては、PL/SQLプログラム・ユニットの追加時間を実行できるようにPLSQL_TIMEOUT接続属性値を変更します。実行中にALTER SESSION文を使用してこの属性を変更することもできます。

    『Oracle TimesTen In-Memory Databaseリファレンス』PLSQL_TIMEOUTを参照してください。

  • TTC_Timeout: TimesTen ClientがTimesTen ServerにSQL文またはPL/SQLブロックの実行をリクエストしたときにTimesTen ClientがTimesTen Serverからのレスポンスを待機する時間の長さを制御します。

  • TTC_ConnectTimeout: SQLDriverConnectリクエストまたはSQLDisconnectリクエストをクライアントが待機する時間を制御します。これは、それらのリクエストに対するTTC_Timeoutの値を上書きします。

    「クライアントのタイムアウト接続属性の選択」を参照してください。

TimesTenクライアント/サーバーを使用する場合は、SQLQueryTimeout (またはSQLQueryTimeoutMSec)およびPLSQL_TIMEOUT (PL/SQLに関連する)をTTC_Timeoutより大幅に小さい値に設定して、クライアントで誤ってレスポンスのないサーバーに対してSQL文またはPL/SQLブロックが長時間実行されることを防ぎます。

PL/SQLを使用する場合、SQLQueryTimeout (またはSQLQueryTimeoutMSec)とPLSQL_TIMEOUTの間の関係は、PL/SQLブロックで使用するSQL文の数によって異なります。ない場合、関係はありません。PL/SQLブロック内のSQL文の最大数がnである場合、PLSQL_TIMEOUTは少なくともn x SQLQueryTimeout (またはn x 1000 x SQLQueryTimeoutMSec)である必要があります(PL/SQLでの処理時間の考慮を含む)。

ノート:

SQLQueryTimeout (またはSQLQueryTimeoutMSec)およびPLSQL_TIMEOUTTTC_Timeoutより十分小さい値に設定されていない場合に、クライアントが誤ってレスポンスのないサーバーに対してSQL文またはPL/SQLブロックを長時間実行して接続を終了すると、サーバーが接続の終了を検知した時点ですぐにSQL文またはPL/SQLブロックが取り消されます。