行パーティション排除について
行パーティション排除は、行パーティション テーブルまたは結合インデックスの問合わせ結果セットを返すためにスキャンする必要のある行パーティション数を制限するメソッド群です。問合わせの検索条件を満たす行を含まない行パーティションをスキップことで、パーティション排除を実行します。行パーティション排除は、自動的に行なわれる最適化です。最適化ルーチンは、問合わせ条件およびパーティション式に基づいて、そのパーティション式の一部の行パーティションに、条件に適合する行が含まれるかどうかを判断します。行が含まれない行パーティションは、ファイル スキャン中にスキップすることができます。特定の問合わせでスキップされる行パーティションは、排除済み行パーティションと呼ばれます。
- 静的
- 遅延
- 動的
Vantageでは、列パーティション化されたテーブルや結合インデックスに対するさまざまな形式の列パーティション排除もサポートしています。列パーティション排除の詳細については、列パーティション排除を参照してください。
リクエスト内の行パーティション排除メソッドの混在
行パーティション排除のメソッドは、同じクエリーの中で混在させることができ、また、テーブルまたは結合インデックスに列と行両方のパーティションがある場合、列パーティション排除のメソッドと混在させることもできます。例えば、静的行パーティション排除は一部のパーティション レベルに使用できます。一方、動的行パーティション排除はその他のレベルに使用することができます。また、一部のレベルでは、行パーティション排除も必要ない場合があります。一部のパーティション レベルでは、複数の形式のパーティション排除を組み合わせることによって、さらにスキャンを簡略化することができます。
複数の行パーティション式がある場合、Vantageは、スキャンが必要なデータ部分集合の数をさらに減らすために、各レベルでの行パーティション排除を組み合わせます。ほとんどの場合、行パーティション化の最大の利点は、パーティション排除から得られます。
Vantageは、複数のレベルの検索条件、またはそれを組み合わせることにより、パーティションを排除できます。
行パーティション排除があると、完全シリンダ読み取りの最適化はサポートされなくなります。このため、パーティション化について検討する際には、その代償についても考える必要があります。最適化ルーチンは、可能な限り行パーティション排除を使用します。ただし、最適化ルーチンは、ブロック読み取りを使用して行パーティションのサブセットを読み取るコストについて、完全シリンダ読み取りを実行するフル テーブル スキャンのコストを見積もりません。ほとんどの場合、行パーティション排除には、完全シリンダ読み取りを実行するフル テーブル スキャンより大きな利点があると考えることができます。
静的行パーティション排除
クエリー最適化の初期の段階で、最適化ルーチンによる行パーティション排除の指定をクエリー条件が許可する場合、使用される行パーティション排除の形式を静的行パーティション排除と呼びます。
パーティション列の単一テーブル制約は、静的行パーティション排除に使用できます。この制約には、システム派生PARTITION列や、システム派生PARTITION#Ln列セットの任意ののメンバーにおける単一テーブル制約が含まれます。ここでは、nの値の範囲は1から62以内になります。
このパーティション排除方法の詳細については、 静的行パーティション排除を参照してください。
遅延行パーティション排除
問合わせ条件が、USINGリクエスト修飾子変数から、または組み込み関数の結果から一部導出された比較に基づいている場合、最適化ルーチンは、その他の場合と同様に、キャッシュされている問合わせ計画を再使用できません。これは、キャッシュされている計画には、この後の実行において検索条件値の変化を処理するのに十分な汎用性が必要だからです。
この場合、最適化ルーチンは、最適化プロセスの後の時点で、特定計画の実行用の値を使用してキャッシュされている計画から最終的な問合わせ計画を構築するときに、行パーティション排除を適用します。この形式のパーティション排除は、遅延行パーティション排除と呼ばれます。
この行パーティション排除方法の詳細については、遅延行パーティション排除を参照してください。
動的行パーティション排除
他のテーブルの値を参照する問合わせ条件が、リクエストが実行されるときに行パーティション排除の実施を許可する場合、その行パーティション排除は動的と呼ばれます。
行パーティション排除を問合わせ実行時に許可する問合わせ条件が、その他のテーブル内の値を参照する場合、問合わせが最適化されたあと、および問合わせの実行中に、AMPデータベース ソフトウェアによって行パーティション排除が動的に実行されます。この形式のパーティション排除は、動的行パーティション排除と呼ばれます。
Vantageは、範囲条件付き動的行パーティション排除と呼ばれる特殊な形式の動的行パーティション排除を使用できます。このパーティション排除は、特定の左テーブル パーティションと右テーブルの行パーティの連続する範囲を結合するときに、その行パーティションの範囲が範囲結合条件から導き出せる場合に使用されます。この形式の動的行パーティション排除は、RANGE_Nパーティション化を使用する単一レベルでパーティション化されたテーブルに対してのみサポートされます。
動的行パーティション排除を使用して、結合を単純化し、そのパフォーマンスを強化することができます。このとき、行パーティション排除に使用するように設計されている結合方法のセットから、最もコストが低い方法が選択されます。
このパーティション排除方法の詳細については、 動的行パーティション排除による積結合を参照してください。
文字パーティションの排除
文字パーティションの排除は行パーティション排除と区別されるものではありませんが、いくつか固有の特徴があります。
文字パーティションは、通常、非文字行パーティション化と比べて少ない数のパーティションを定義します。パーティションCHECK制約には16,000文字という制限があるので、文字パーティションの実効制限は約2,000パーティションです(パーティションCHECK制約とその各種形式の詳細について、<Teradata Vantage™ - データベースの設計、B035-1094>または<Teradata Vantage™ - SQLデータ定義言語 - 詳細トピック、B035-1184>の「CREATE TABLE」を参照)。結果として、非常に大きなテーブルに対して文字パーティションを指定する場合、通常はマルチレベル パーティション式の一部として指定するのが最も効果的です。
定義可能な組み合わせパーティションの最大数までの文字パーティション化されたテーブルの場合、複数のパーティション レベルでパーティション排除を組み合わせてから、1/2000というおおよその制限から読み取る必要のある組み合わせパーティションの比率を減少させることができます。
例えば、次のテーブルは、65,475のパーティションを定義します。内部パーティション番号を2バイトと仮定すると、このパーティション数は2バイトのパーティション化に定義できる組み合わせパーティションの最大数65,535に近い数です。この場合、27の行パーティションがレベル1に定義され、485の行パーティションがレベル2に、5つの行パーティションがレベル3に定義されます。
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 OR UNKNOWN), RANGE_N(activity_date BETWEEN DATE '1998-10-01' AND DATE '2007-12-31' EACH INTERVAL '7' DAY, NO RANGE, UNKNOWN), RANGE_N(revenue_code BETWEEN 1 AND 4 EACH 1, NO RANGE OR UNKNOWN ));
組み合わせパーティションに均等に行を分散すると仮定すると、次のSELECTリクエストは1つの組み合わせパーティションにのみアクセスします。または、markets内の行の1/65,475です。
SELECT * FROM markets WHERE productname BETWEEN 'a' AND 'az' AND activity_date=DATE '2007-08-15' AND revenue_code=1;
Vantageでは、文字パーティション レベルで行パーティション排除を使用し、さらに他のパーティション レベルでのパーティション排除を併用して、文字パーティション化されたテーブルのみを使用する場合よりもアクセスするデータの部分集合を減らすことができます。これは文字パーティション化されたテーブルで定義できる行パーティションの最大数が約2,000に制限されているためです。
BEGINおよびEND期間範囲関数を指定する行パーティション化の静的および遅延行パーティション排除
BEGINおよびEND期間範囲関数を指定する期間式については、静的行パーティション排除および遅延行パーティション排除のみがサポートされます。
- BEGINおよびEND期間範囲関数による直接パーティション化。
- BEGINおよびEND期間範囲関数を使用するCASE_N関数によるパーティション化。
- BEGINおよびEND期間範囲関数を使用するCASE関数によるパーティション化。
- BEGINおよびEND期間範囲関数を使用するRANGE_N関数によるパーティション化。
データベースは、アクセスするテーブルがBEGINまたはEND期間範囲関数を基にしてパーティション化を定義されていて、かつユーザーがWHERE句でBEGINまたはEND期間範囲関数の等号制約を指定している場合のみ、単一パーティション スキャンを実行します。
単一パーティション スキャンを実行するためのルールは次のとおりです。
テーブルのパーティション化に使用されている期間範囲関数 | WHERE句で等号制約が指定されている関数 | データベースの動作 |
---|---|---|
BEGIN | BEGIN期間範囲関数 | 単一パーティションのアクセス。 |
END期間範囲関数 | 単一パーティションのアクセスを実行しない。 | |
BEGIN期間範囲関数とEND期間範囲関数の両方 | 単一パーティションのアクセス。 | |
END | BEGIN期間範囲関数 | 単一パーティションのアクセスを実行しない。 |
END期間範囲関数 | 単一パーティションのアクセス。 | |
BEGIN期間範囲関数とEND期間範囲関数の両方 | 単一パーティションのアクセス。 | |
BEGINおよびEND | BEGIN期間範囲関数 | 単一パーティションのアクセスを実行しない。 |
END期間範囲関数 | 単一パーティションのアクセスを実行しない。 | |
BEGIN期間範囲関数とEND期間範囲関数の両方 | 単一パーティションのアクセス。 |
これらのルールを示す例として次のテーブル定義を想定できます。
CREATE SET TABLE t11 ( a INTEGER, b PERIOD(DATE)) PRIMARY INDEX(a) PARTITION BY CAST((BEGIN(b)) AS INTEGER; CREATE SET TABLE t12 ( a INTEGER, b PERIOD(DATE)) PRIMARY INDEX(a) PARTITION BY CAST((END(b)) AS INTEGER);
次の例では、関連するEXPLAINテキスト句を太字で強調表示しています。
EXPLAIN SELECT * FROM t11 WHERE END(b)=DATE ‘2010-02-03’;次に、EXPLAIN出力の一部を示します。
... 3) We do an all-AMPs RETRIEVE step from df2.t11 by way of an all-rows scan with a condition of ("(END(df2.t11.b ))= DATE '2010-02-03'") into Spool 1 (group_amps), which is built locally on the AMPs. The size of Spool 1 is estimated with no confidence to be 1 row (56 bytes). The estimated time for this step is 0.03 seconds.
次のSELECTリクエストは、WHERE句の述部がEND期間範囲関数で定義され、パーティション式がEND期間範囲関数上で等号制約を使用して定義されているので、単一パーティション スキャンを実行します。
EXPLAIN SELECT * FROM t12 WHERE END(b)=DATE ‘2011-02-03’; ... 3) We do an all-AMPs RETRIEVE step from a single partition of df2.t12 with a condition of ("df2.t12.b = PERIOD(DATE '2011-02-03' - INTERVAL '1' DAY, DATE '2011-02-03')") with a residual condition of ( "(END(df2.t12.b ))= DATE '2011-02-03'") into Spool 1 (group_amps), which is built locally on the AMPs. The size of Spool 1 is estimated with no confidence to be 1 row (56 bytes). The estimated time for this step is 0.03 seconds. ...
次のSELECTリクエストは、WHERE句の述部がEND期間範囲関数で定義され、パーティション式がEND期間範囲関数上で等号制約を使用して定義されているので、単一パーティション スキャンを実行します。
EXPLAIN SELECT * FROM t12 WHERE a=1 AND END(b)=DATE ‘2011-02-03’;
...
1) First, we do a single-AMP RETRIEVE step from a single partition of
df2.t12 by way of the primary index "df2.t12.a = 1,
df2.t12.b = PERIOD (DATE '2011-02-03'- INTERVAL '1' DAY, DATE
'2011-02-03')" with a residual condition of ("((END(df2.t12.b ))=
DATE '2011-02-03') AND (df2.t12.a = 1)") into Spool 1 (one-amp),
which is built locally on that AMP. The size of Spool 1 is estimated
with low confidence to be 1 row (56 bytes). The estimated time for
this step is 0.02 seconds.
テーブルがBEGINおよびEND期間範囲関数を使用して直接行パーティション化されたために数値になっている場合、およびパーティション式で指定されているパーティション列がリクエスト内の条件に指定されている場合は常に、データベースは、他のDateTime式に適用されるものと同じBEGINおよびEND期間範囲関数のルールを使用して、行パーティション排除を実行します。
次のテーブル定義を想定します。
CREATE SET TABLE t1 ( a INTEGER b PERIOD(DATE) PRIMARY INDEX(a) PARTITION BY CAST((END(b) AS INTEGER);
次のSELECTリクエストは、t1の55,333の行パーティションをスキャンします。
EXPLAIN SELECT * FROM t1 WHERE b>PERIOD(DATE ‘1901-02-02);
...
3) We do an all-AMPs RETRIEVE step from 55333 partitions of
df2.T1 with a condition of ("df2.T1.b > (PERIOD (DATE '1901-02-02',
DATE '1901-02-02'))") into Spool 1 (group_amps), which is built
locally on the AMPs. The size of Spool 1 is estimated with no
confidence to be 1 row (56 bytes). The estimated time for this
step is 0.03 seconds.
...
BEGINまたはEND期間範囲関数を指定するCASE_N関数またはCASE関数を使用してテーブルが行パーティション化される場合、DateTime式を使用した行パーティション排除の既存のルールも適用されます。
次のテーブル定義を想定します。
CREATE TABLE orders ( o_orderkey INTEGER NOT NULL, o_custkey INTEGER, o_orderperiod PERIOD (DATE) NOT NULL, o_orderpriority CHARACTER (21), o_comment VARCHAR (79)) PRIMARY INDEX(o_orderkey) PARTITION BY CASE_N(END(o_orderperiod) <= DATE '2010-03-31', /*Q1*/ END(o_orderperiod) <= DATE '2010-06-30', /*Q2*/ END(o_orderperiod) <= DATE '2010-09-30', /*Q3*/ END(o_orderperiod) <= DATE '2010-12-31' /*Q4*/ );
次のSELECTリクエストは、ordersの2つの行パーティションをスキャンし、最初の2四半期に行なわれた発注の詳細を表示します。
EXPLAIN SELECT * FROM orders WHERE END(o_orderperiod) > DATE '2010-06-30';
...
3) We do an all-AMPs RETRIEVE step from 2 partitions of
df2.orders with a condition of (
"(END (df2.orders.O_orderperiod))> DATE '2010-06-30'")
into Spool 1 (group_amps), which is built locally on the AMPs.
The size of Spool 1 is estimated with no confidence to be 1 row (
167 bytes). The estimated time for this step is 0.03 seconds.
...
テーブルがBEGINまたはEND期間範囲関数を指定したRANGE_N関数を使用して行パーティション化されている場合、およびパーティション式で指定されている列がリクエスト内の条件に指定されている場合は常に、Teradata Databaseは、DateTime式に適用されるものと同じルールを使用して行パーティション排除を実行します。
次の定義を使用して、sales_historyテーブルを定義するとします。
CREATE TABLE sales_history ( product_code CHARACTER(8), quantity_sold INTEGER, transaction_period PERIOD(DATE)) PRIMARY INDEX (product_code) PARTITION BY RANGE_N(END (transaction_period) BETWEEN DATE '2006-01-01' AND DATE '2015-12-31' EACH INTERVAL'1' YEAR);
次のSELECTリクエストは、2010年より前のsales_historyの5つの行パーティションをスキャンします。
EXPLAIN SELECT * FROM sales_history WHERE transaction_period < PERIOD(DATE '2010-01-01');
...
3) We do an all-AMPs RETRIEVE step from 5 partitions of
df2.sales_history with a condition of (
"df2.sales_history.transaction_period < (PERIOD (DATE '2010-01-01',
DATE '2010-01-01'))") into Spool 1 (group_amps), which is built
locally on the AMPs. The size of Spool 1 is estimated with no
confidence to be 1 row(64 bytes). The estimated time for this step
is 0.03 seconds.
...
RANGE_Nパーティション式でBEGINまたはEND範囲関数が指定され、問合わせ条件に同じパーティション式が含まれている場合、最適化ルーチンは行パーティション排除を使用します。
次のSELECTリクエストは、sales_historyテーブルの4つの行パーティションをスキャンして、2010年より前のすべての販売履歴を表示します。
EXPLAIN SELECT * FROM sales_history WHERE END (transaction_period) < DATE '2010-01-01';
...
3) We do an all-AMPs RETRIEVE step from 4 partitions of
df2.sales_history with a condition of (
"(END(df2.sales_history.transaction_period ))< DATE
'2010-01-01'") into Spool 1 (group_amps), which is built locally
on the AMPs. The size of Spool 1 is estimated with no confidence
to be 1 row (64 bytes). The estimated time for this step is 0.03
seconds.
...