静的行パーティション排除について
静的行パーティション排除によって、データベースが問合わせに返信するために読み取って処理する必要があるデータ ブロックの数を大きく減らすことができます。これは、特に複数のレベルで適用すると有効です。静的行パーティション排除は、パーティション列とシステム派生列(PARTITIONおよびPARTITION#L n)に対する定数条件に基づきます。定数条件という用語は、等式、不等式、BETWEENのようなリテラル値と述部条件、特定計画のすべてのCURRENT_TIME、CURRENT_TIMESTAMP、またはUSING値の置換、およびすべてのDATE、CURRENT_DATE、TEMPORAL_DATEまたはUSERの値の置換を意味します。
データベースは、静的行パーティション排除を各レベルに個別に適用し、その結果を単一の行パーティション排除リストに組み合わせます。システムが、あるレベルにあるどの行パーティションも排除できない場合、そのレベルではすべての行パーティションを処理しなければなりません。単一レベルの行パーティションに使用されるのと同じアルゴリズムが、各レベルで使用されます。システム派生PARTITION#L n列における条件は例外です。この場合、行パーティション排除アルゴリズムは、システム派生PARTITION列における条件の代わりに、レベルnについて検討します。システムは、システム派生列PARTITIONとシステム派生列PARTITION#L1の両方で、単一レベルの行パーティションについての条件を検討します。
8バイト パーティションのテーブルまたは結合インデックスの静的パーティション排除は、8,000パーティションに制限され、そのテーブルまたは結合インデックスに対しては、それ以上の静的パーティション排除は発生しません。データベースは静的パーティション排除を最初のパーティション レベルに対して適用してから、2番目のパーティション レベルに適用します。これは、パーティション排除が完了するか、非排除パーティションが8,000という制限に達するまで続けられます。制限に達すると、そのレベルの残りのパーティションとそれ以下のレベルは排除されません。
パーティション式のパーティション列に定数の等号制約がある場合、静的行パーティション排除が実行されます。すべてのパーティションではなくそのパーティション式に対して指定された行パーティションが排除されます。
最適化ルーチンがパーティション排除の機会を検出する機能には限度があるので、最適化ルーチンが論理的に排除可能なすべての行パーティションを常に排除できるとは限りません。
EXPLAINリクエスト修飾子を常に実行して、実際のシステム パフォーマンスを測定し、適正なパーティション排除とパフォーマンスが、期待されるパーティション スキーマとワークロードで発生することを確認してください。検証テストの結果が受け入れ可能でない場合、または期待したパフォーマンス レベルでない場合は、別のパーティション スキーマを使用すること、またはパーティションを使用しないことを検討し、データベースを物理的に変更するか問合わせを変更(パーティション列に定数の条件を追加するなど)して、必要なレベルのパフォーマンスを確保します。
RANGE_Nパーティション式の静的行パーティション排除
- 行パーティション列。
- 認識される線形式のCAST、Teradata変換、またはEXTRACT。
- 2つの認識される線形式の合計。
- 認識される線形式および定数式の合計。
- 定数式および認識される線形式の合計。
- 認識される線形式および定数式の差。
- 行パーティション列と定数式の積、定数式の値は0より大きい。
- 定数式と行パーティション列の積、定数式の値は0より大きい。
- 行パーティション列を定数式で割った値、定数式の値は0より大きい。
- CASE_N行パーティション式(CASE_N式内の条件が、指定された問合わせ条件に適合しないと最適化ルーチンが認識した場合)。
このリストには、考えられるすべての非減少線形式が含まれているわけではありません。リストに含まれていない式は、データベースによって静的行パーティション排除の対象として認識されません。
CASE_N行パーティション式の静的行パーティション排除
CASE_N行パーティション式内の条件が、指定の問合わせ条件に適合しないと最適化ルーチンが認識した場合、CASE_N行パーティション式に対して静的行パーティション排除を実施することがあります。
文字パーティション式の静的行パーティション排除
RANGE_N文字パーティションの行パーティション排除については、特別な考慮事項があります。
例えば、RANGE_N条件が終了値を指定していない範囲を指定し、part_col > range_endという形式の条件があり、range_endが次の範囲の始まりの文字列と一致している場合があります。ただし、次の例のt1のパーティション式で実行されるように、最後の文字位置にある次の最下位のコードと文字を置換する場合は除きます。
CREATE TABLE t1( i INTEGER, j CHARACTER(4), k INTEGER) PRIMARY INDEX(i) PARTITION BY (RANGE_N(j BETWEEN 'aaaa','cccc','eeee','gggg', 'iiii','kkkk','mmmm','oooo', 'qqqq','ssss' AND 'tttt', NO RANGE));
次のSELECTリクエストは、応答セットを返すためには8個の行パーティションのみを読み取る必要があるにもかかわらず、9個の行パーティションを読み取ります。これは、行パーティション2の範囲の終了値'eeed'が暗黙的であり、RANGE_N式で明示的に指定されていないために起こります。
SELECT * FROM t1 WHERE j > 'eeed';
INTEGERおよびDATEデータの場合、最適化ルーチンは、次の範囲の開始値から1(または1日)を引いて範囲の終了値を見つけることができますが、特定の照合シーケンスを基にして、文字内の次の最低または最高のコード ポイントを判断することはできません。結果として、そのような場合、行パーティション排除では、常に読み取る必要がある行パーティションよりも1つ余計にパーティションが検出されます。
行パーティション排除は、RANGE_Nパーティションに対してLIKE述部でpart_col LIKE 'abc%'の形式でサポートされます。'abc'は任意の文字列リテラルを表わします。検索文字列内に存在する0以上の文字から成る任意の文字列と一致する'%'メタ文字は、文字列の最後の文字としてのみ存在する可能性があります(サーバーの文字セットによっては、これはASCIIの'%'ではなく、_unicodeの'FF05'XCによる全角のパーセントなどの異なるコード ポイントになります)。任意の1文字と一致させる'_'メタ文字を使用すると、含まれている述部からの行パーティション排除が実行されなくなります。
CASE_N文字パーティションを使用するLIKE述部では行パーティション排除は保証されません。これは、CASE_Nを使用する行パーティション排除が、LIKE述部でSAT-TCがサポートされていることに依存するためです。
問合わせ内でLIKE述部が指定されているときに最適化ルーチンで行パーティションを排除するには、RANGE_Nパーティション式を使用して文字パーティションを定義するのが最善の方法です。=、<、>、<=、>=、<>、BETWEENなどの他の比較演算子がCASE_N式内およびWHERE句の述部に指定されている場合、非文字パーティションと同じように、CASE_N文字パーティションを使用して行パーティション排除が実行される必要があります。
行パーティション排除は、述部を評価できる必要があり、そのような述部を実行するためにパーティション列データの変換は必要ありません。
述部内の定数式の文字セットからパーティション列の文字セットへの有効な変換が比較内にない場合、データベースによってどちらもUnicodeに変換されます。この処理が実行された場合、行パーティション排除は実行されません。
行パーティション排除の実行可能性を高めるために、文字パーティション化されたテーブルのパーティション列がUnicodeサーバー文字セットを使用して保存されるようにする必要があります。
文字データをCASTすると、文字列が切り捨てられて、情報が失われる可能性があります。
行パーティション排除のレベルを満たしている述部が等式条件ではない限り、テスト値にCASTまたは他のデータ変換操作が含まれている場合、データベースはRANGE_Nパーティションの行パーティション排除をサポートしません。
RANGE_Nパーティションの静的行パーティション排除を行なうには、上限が設定されていない範囲が存在してはなりません。つまり、最初の範囲の先頭または最後の範囲の末尾のアスタリスク文字が指定されているということです。この制限は、文字RANGE_Nパーティション レベルの静的行パーティション排除にも適用されます。行パーティション排除のレベルを満たしているWHERE句の述部が等価条件である場合はこの制限に例外があり、そのレベルで静的行パーティション排除が実行されます。
- 静的行パーティション排除の条件を満たすには、行パーティション レベルに存在する文字パーティション列が1つ以下である必要があります。
- 静的行パーティション排除のレベルを満たすWHERE句の条件の大文字小文字の区別が、そのレベルのパーティション式に指定するすべての比較の大文字小文字の区別と一致している必要があります。
パーティション式のすべての非定数式のすべての文字列関数と列属性修飾子の大文字小文字の区別が、WHERE句の条件で指定された関数および修飾子の大文字小文字の区別と一致している必要があります。
次の内容は、大文字小文字を区別します。
- LOWER
- SOUNDEX
- UPPER
- UPPERCASE修飾子
次の場合は、大文字小文字が区別されます。
- CHAR2HEXINT
- TRANSLATE
- TRANSLATE_CHK
- TRIM
- VARGRAPHIC
次の関数は、比較演算子と同じルールに従います。データベースは、関数入力と、ANSIまたはTeradataというセッション モードでデフォルトの大文字小文字の区別を調べて、大文字小文字の区別を判断します。- INDEX
- MINDEX
- POSITION
SUBSTRING関数の存在は、大文字小文字の区別に影響しません。
条件内の非定数式を含むいずれかの比較関数または文字列関数の大文字小文字が区別されない場合、WHERE句の条件では大文字小文字が区別されないと見なされます。
- パーティション式内に非定数式を使用する連結演算子が存在すると、そのレベルで静的行パーティション排除を実行できません。
- DMLリクエストのセッションの照合がテーブルの照合と一致している必要があります。
- 行パーティション排除のレベルを満たす述部が等式条件でない限り、パーティション式でRANGE_N関数を指定する場合、そのテスト値は、CASTまたはUPPERCASEなどのデータ変換修飾子を使用しない単一列の参照でなければなりません。
静的行パーティション排除を可能にするWHERE句の述部は、単一列の参照と定数式の間の比較でなければなりません。
WHERE句の述部で列参照にCAST式またはUPPERCASEなどのデータ変換修飾子を指定する場合、最適化ルーチンは、その述部の行パーティション排除を適用しません。
これらのルールは非文字パーティション レベルの静的行パーティション排除には適用せず、非文字ベースのパーティション レベルで行パーティション排除を実行するために、セッション照合とテーブル照合が一致している必要はありません。
- || (連結演算子)
- LOWER
- SOUNDEX
- SUBSTRING/SUBSTR
- TRANSLATE
- TRIM
- UPPER
- VARGRAPHIC
例えば、次の文字パーティション定義があるとします。
CREATE MULTISET TABLE df2.t4, NO FALLBACK, NO BEFORE JOURNAL, NO AFTER JOURNAL, CHECKSUM=DEFAULT ( a INTEGER, b CHARACTER(4) CHARACTER SET UNICODE NOT CASESPECIFIC) PRIMARY INDEX (a) PARTITION BY RANGE_N(b BETWEEN 'A' AND 'F','FA' AND 'Z');
次のSELECTリクエストは、WHERE句に連結演算子とSOUNDEX関数を指定しているので、1つの行パーティションのみから読み取ります。
SELECT * FROM t4 WHERE b BETWEEN 'a'||'a' AND SOUNDEX('d');
ただし、述部内でパーティション列に文字列関数を指定すると、行パーティション排除が使用される可能性がなくなります。例えば、テーブルt4に対する次のSELECT要求について考えてみます。この要求では、TRIM関数が列bに対して指定され、この列はt4の文字パーティション列なので、最適化ルーチンは結果セットを返すために静的行パーティション排除を適用しません。
SELECT * FROM t4 WHERE TRIM(trailing ' ' FROM b) BETWEEN 'a' AND 'd';
データベースは、ANSIセッション モードで発行されたリクエストを、Teradataセッション モードで実行依頼されたリクエストとは異なる方法で処理します。
ANSIセッション モードでは、データベースは、列参照をCASESPECIFICになるように内部的に変換することによって、NOT CASESPECIFIC列と大文字小文字を区別する修飾子を含まない定数の間のすべての単一テーブル条件を処理します。このためその条件が無効になり行パーティション排除で使用されなくなるので、ANSIセッション モードで最適化ルーチンにより行パーティション排除を適用させる場合は、CASESPECIFICとして文字パーティション列を作成する必要があります。または、問合わせのWHERE句の述部内のすべての定数をNOT CASESPECIFICになるようにキャストすることができます。
例えば、次のテーブル定義があるとします。
CREATE MULTISET TABLE MWS2.t4, NO FALLBACK, NO BEFORE JOURNAL, NO AFTER JOURNAL, CHECKSUM=DEFAULT ( a INTEGER, b CHARACTER(4) CHARACTER SET UNICODE NOT CASESPECIFIC) PRIMARY INDEX (a) PARTITION BY RANGE_N(b BETWEEN 'A' AND 'F', 'FA' AND 'Z');
ANSIセッション モードでは、列bに対する暗黙的なCASTのために、データベースはすべての行パーティションを読み取ります(静的行パーティション排除は適用されません)。
SELECT * FROM t4 WHERE b BETWEEN 'a' and 'd' ;
次のように同じリクエストを少し変更すると、列bの明示的なCASTのために、データベースは1つの行パーティションのみから読み取ります。
SELECT * FROM t4 WHERE b BETWEEN CAST ('a' AS CHARACTER(4) NOT CASESPECIFIC) AND CAST ('d' AS CHARACTER(4) NOT CASESPECIFIC);
次の例は、Teradataセッション モードでの文字パーティション列に対するSELECTリクエストの動作を示しています。最初に、次のテーブルを作成します。
CREATE TABLE markets ( productname VARCHAR(50) NOT CASESPECIFIC, region BYTEINT NOT NULL, activity_date DATE FORMAT 'yyyy-mm-dd' NOT NULL, revenue_code BYTEINT NOT NULL, business_sector BYTEINT NOT NULL, note VARCHAR(256)) PRIMARY INDEX (productname, region) PARTITION BY (RANGE_N(productname BETWEEN 'A','B','C','D','E','F', 'G','H','I','J','K','L', 'M','N','O','P','Q','R', 'S','T','U','V','W','X', 'Y', 'Z' AND 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ', NO RANGE, UNKNOWN));
次の問合わせに関連付けられているコメントでは、パーティションごとに、行パーティションおよび多くのデータ ブロック間で行が均等に配分されていると仮定しています。静的行パーティション排除は使用できないので、これらの問合わせは、全AMPのフル テーブル スキャンになります。
最初のSELECTリクエストは、全AMP上の2つの行パーティションを読み取ります。これは、データベースがmarketsテーブルのデータ ブロックの約2/28を読み取ることを意味します。
SELECT * FROM markets WHERE productname LIKE 'B%';
次のSELECTリクエストは、全AMP上の1つの行パーティションのみを読み取ります。そのためデータベースは、marketsのデータ ブロックの約1/28を読み取ります。
SELECT * FROM markets WHERE productname < 'B';
次のSELECTリクエストは、全AMP上の2つの行パーティションを読み取ります。そのためデータベースは、marketsのデータ ブロックの約2/28を読み取ります。
SELECT * FROM markets WHERE productname LIKE UPPER('B%');
次の例では、KANJIEUC_0Uセッション文字セットとJIS_COLL照合を使用します。
CREATE TABLE t12 ( a INTEGER, b VARCHAR(15) CHARACTER SET GRAPHIC) PRIMARY INDEX(a) PARTITION BY (RANGE_N(b BETWEEN _GRAPHIC '9758'XC AND _GRAPHIC '9759'XC, NO RANGE, UNKNOWN));
次のSELECTリクエストは、全AMP上の1つの行パーティションを読み取ります。
SELECT * FROM t12 WHERE b BETWEEN _GRAPHIC '9758'XC AND _GRAPHIC '9759'XC;