17.00 - 17.05 - 述部簡略化 - Advanced SQL Engine - Teradata Database

Teradata Vantage™ - SQLリクエストおよびトランザクション処理

Product
Advanced SQL Engine
Teradata Database
Release Number
17.00
17.05
Published
2020年6月
Content Type
プログラミング リファレンス
ユーザー ガイド
Publication ID
B035-1142-170K-JPN
Language
日本語 (日本)

述部簡略化は、問合わせを同等のフォームに変換するクエリー リライト システムの一部ですが、問合わせの最適化よりもさらに単純で修正可能です。この節では、述部簡略化の主なカテゴリをいくつか紹介します。

実現可能性および推移閉包

SAT-TC(実現可能性および推移閉包)の書き換えでは、述部のセットを分析して、次の任意のを活用してリクエストを書き換えできるかどうかを判断します。

  • 矛盾

    単純な例として、a=1 AND a=0のような条件があります。

  • 推移閉包を使用した、既存の述部セットからの新しい述部の推測。

    例えば、述部a=1 AND a=bを指定するリクエストを考えてみます。これはb=1を意味し、書き換えまたはリクエストの最適化に有効な情報になる可能性があります。

推移的閉包を使用して新しい条件を派生するその他の例には、次のような例があります。

     A=B AND A=C --> B=C
     A=5 AND A=B --> B=5
     A=5 AND A IS NULL --> FALSE
     A=5 AND A IS NOT NULL --> A=5
     X > 1 AND Y > X --> Y >= 3
     X IN (1,2,3) AND Y=X --> Y IN (1,2,3)

推移的閉包は、抽出述部のコンテキストにも適用されます。例えば、条件のセット{o_orderdate=‘1999-05-01’ AND EXTRACT(MONTH FROM o_orderdate)>2}については、システムはo_orderdate=‘1999-05-01’に基づいてo_orderdate=‘1999-05-01’,を追加します。これは、問合わせの既存のEXTRACT述部を簡略化するために使用できます。

Periodデータ型の列にBEGIN…END制約を使用して指定されたDMLリクエストの一部のカテゴリの場合、クエリー リライト システムは、実現不可能な条件を識別するために暗黙的な制約BEGIN(column_1) <END(column_1)を追加します。これらの実現不可能な条件が発生した場合、EXPLAINテキスト句unsatisfiableを使用し、問合わせのEXPLAINテキストによりそれらを識別します(EXPLAINリクエスト修飾子句の用語を参照)。

例えば、以下のテーブル定義があるとします。

CREATE TABLE t1 (a INTEGER b PERIOD (DATE));

次の問合わせを使用するとします。

SELECT *
FROM t1
WHERE BEGIN(b) > DATE ‘2010-02-03’ AND
      END(b) < DATE ‘2010-02-03’;

クエリー リライト システムは、暗黙的な制約BEGIN(b) < END(b)を追加し、問合わせ述部と組み合わせて実現不可能を派生することができます。

クエリー リライト システムは、推移的閉包を問合わせブロック全体、つまり外部問合わせブロックと内部問合わせブロック間の推移的閉包に適用することもできます。このため条件をsubquery に後付け、およびsubquery から排除できます。基本の方式は、推移的閉包を計算する前に問合わせブロック条件を組み合わせることです。INおよびNOT IN演算子は、それぞれ=およびとして扱われます。派生条件が各問合わせブロックに適切に追加されます。

単純なSQLの例について考えてみます。次のSELECTリクエストは、x<1を意味します。

     SELECT * FROM t1 WHERE x IN (SELECT y FROM t2 WHERE y<1);

同様に、次のSELECTリクエストは、x <3でyが(1,4)に含まれることを意味します。

    SELECT *
     FROM t1
     WHERE EXISTS (SELECT *
                   FROM t2
                   WHERE y<3
                   AND   x=y)
                   AND   x IN (1,4);

このコンテキストでは、分析時の条件が接続条件として参照されています。接続条件は、外部問合わせとsubquery とを接続する条件です。接続条件についての詳細は、接続述部を参照してください。

推移閉包の適用

推移閉包(TC)は、日付範囲およびIN句を最適化できます。次のリクエストは、このようなケースの1つを示しています。

     SELECT l_shipmode, SUM (CASE
                                 WHEN o_orderpriority = '1URGENT'
                                 OR   o_orderpriority = '2-HIGH'
                                 THEN 1
                                 ELSE 0
                             END)
     FROM lineitem
     WHERE l_commitdate  <  l_receiptdate
     AND   l_shipdate    <  l_commitdate
     AND   l_receiptdate >= '1994-01-01'
     AND   l_receiptdate < ('1994-06-06')
     GROUP BY l_shipmode;

派生する可能性のある制約の新しい集合は、次のとおりです。

        (l_shipdate < l_receiptdate AND
        l_commitdate <= '1994-06-04' AND
        l_shipdate   <= '1994-06-03')

lineitemまたはカバー インデックスの1つがl_shipdateで値順に並べられるか行パーティション化される場合、新しい制約のl_shipdate<='1994-06-03'によって、Teradata Databaseはフル テーブル スキャンを実行する代わりにテーブルの一部のみにアクセスできるようになります。

一部の問合わせでは、TCが追加する述部によって、パフォーマンスが向上することがあります。追加の述部は、それらを使用するリクエストについてのEXPLAINレポートでも確認できます。

SAT-TCおよびクエリー リライト

クエリー リライトで推移的閉包を使用する重要な側面として、それがONおよびWHERE句に適用されることが挙げられます。例えば、次のリクエストがあるとします。

     SELECT product_name, sum(amount*quantity) AS qty
     FROM product LEFT OUTER JOIN sales1
     ON product_key=sales_product_key
     WHERE product_key=10
     GROUP BY product_key, product_name ;

このリクエストでは、推移閉包によって、推測される述部sales_product_key=10がON句に追加されます。これは、ON句に追加された述部が、結合内の内部テーブルのプライマリ インデックスにおける制約であるときに特に効果的です。

推移的閉包の重要な特性として、連続的な内部結合のON句に新しい述部を推測する機能もあります。例えば、次のリクエストについて考えてみます。

     SELECT product_key, product_name, SUM(s1.amount * s1.quantity+s2.amount * s2.quantity) 
     AS total
     FROM product LEFT OUTER JOIN ((sales1 AS s1 INNER JOIN store
                  ON  s1.sales_store_key=store_key)
                  INNER JOIN sales2 AS s2
                  ON  s2.sales_store_key=store_key
                  AND s2.sales_store_key=10)
                  ON  product_key=s1.sales_product_key
                  AND product_key=s2.sales_product_key
     GROUP BY product_key, product_name;

推移閉包のこの適用を確認するために、s1、s2、およびstore間の連続的な内部結合について考えてみます。連続的な内部結合の述部は、単一のWHERE句で指定されているかのように、推移閉包でまとめて扱うことができます。この例では、推移閉包は、これらの述部が次の複合述部として出現したかのように処理します。

     WHERE s1.sales_store_key = store_key
     AND   s2.sales_store_key = store_key
     AND   s2.sales_store_key = 10

このように述部を論理的にグループ化することによって、推移閉包は新しい述部のstore_key=10s1.sales_store_key=10を導出でき、それらを連続的な内部結合セット内の一番上の内部結合のON句に配置できます。この例では、s2に結合するON句にあたります。

条件が算術的にFALSEの場合、矛盾またはunsatisfiableと表現します。この文脈では、矛盾の反対語は、データに関係なく、実現可能です。例えば、同じリクエスト内でa=1およびa=2条件を指定する可能性があります。クエリー リライトは、そのような実現不可能な条件の存在を検出した場合、すべての結合および検索が単一のAMPベース上で実行できるように条件を単純化および最適化します。

矛盾する条件を利用する1つの方法として、CHECK制約をテーブルに追加する方法があります。こうすると、クエリー リライトで不必要な条件を排除し、最適化ルーチンでより優れた実行計画を構築することができます(推移閉包の適用を参照)。

例えば、事業年度の最初の3か月に行なわれたすべての発注のリストを作成したいとします。orders1、orders2、...orders12のUNION ALLであるordertblビューにのみアクセスできる場合、クエリーは以下のようになります。

    SELECT *
    FROM order_tbl
    WHERE EXTRACT(MONTH FROM o_orderdate)<= 3;

リクエストを満たすにはorders1、orders2、およびorders3にのみアクセスすることが必要だとしても、CHECK制約がない場合は、システムは制約EXTRACT(MONTH FROM o_orderdate)<=3を使用してテーブルorders1、orders2、...orders12のすべてにアクセスする必要があります。クエリー リライトが残りの9つのテーブルをフィルタで除外することを認識するための唯一の方法は、すべてのテーブルにCHECK制約を追加し、CHECK制約とクエリー制約との間の矛盾を判別することです。

例えば、order4のCHECK制約が追加される場合、クエリー リライトでは、次の複合述部が矛盾していることが検出されます。

     EXTRACT(MONTH FROM o_orderdate)<= 3     -- from query
     AND
     EXTRACT(MONTH FROM o_orderdate)=4       -- from CHECK constraint

この特別なケースにおいて、クエリー リライトはこのステップを単純に排除することができます。一般に、クエリー リライトは、一連の条件が実現可能であることを認識している必要があります。

当然ながら、a=1 AND a=2などのように、データと関係なく結果を返さない矛盾した問合わせを実行依頼することはまれでしょう。前の段落の例は、そのようなチェックの必要性を示すためのものです。前述の通り、この問題は実現可能性の問題と呼ばれます。実現可能性のためのすべてのソリューションは一連の条件を生成し、それらをFALSEと宣言して矛盾していることを示すか、または特定のデータでは一連の条件が実現可能であることを意味するTRUEと宣言します。

水平にテーブルをパーティション化するためにCHECK制約を使用する場合、CHECK制約の実行コストを認識する必要があります。このタイプのテーブルのパーティション化は、テーブルまたは結合インデックスに対してPARTITION BY句のパーティション式で指定できる行パーティション化と概念的には類似していますが同一ではありません。

SAT-TCおよび問合わせの最適化

問合わせの最適化によって、結合インデックスの使用および保守に、以下追加の実現可能性が適用されます。

  • 1つ以上の基本テーブル上で、結合インデックスが更新操作と同期するように更新する必要があるかどうかを確認する。ここでの更新操作という用語は、当該の基本テーブルに対する挿入、更新、または削除操作を意味します。
  • 結合インデックスが問合わせを部分的にカバーしているかまたは完全にカバーしているかを判別する。

結合インデックスの更新問題は、結合インデックス条件と、基本テーブルの保守に適用される条件とを合わせたものに実現可能性のチェックを使用することで解決できます。

次のスパース結合インデックス定義を想定します。

     CREATE JOIN INDEX j1 AS
       SELECT *
       FROM lineitem
       WHERE EXTRACT (MONTH FROM l_shipdate)<=6;

     CREATE JOIN INDEX j2 AS
       SELECT *
       FROM lineitem
       WHERE EXTRACT(MONTH FROM l_shipdate)>=7;

ここで、例としてlineitemテーブルに対する次の削除操作を考慮してください。

     DELETE lineitem
     WHERE EXTRACT(MONTH FROM l_shipdate)=12;

これは、j2は更新する必要があり、j1にはその必要がないことを示唆しています。実現可能性チェックは次の述部についてTRUEを返すので、システムはこの決定を行なうことができます。

     EXTRACT(MONTH FROM l_shipdate)=12
     AND
     EXTRACT(MONTH FROM l_shipdate)>=7

ただし、この述部についてはFALSEを返します。

     EXTRACT(MONTH FROM l_shipdate)=12
     AND
     EXTRACT(MONTH FROM l_shipdate)<=6

結合インデックスがクエリーを完全にカバーするかまたは部分的にカバーするかを判別する問題は、一連の実現可能性の問題として解決されます。この問題での実現可能性の使用は、結合インデックス定義内でWHERE句の述部に定数が指定されるなどのより複雑な条件がある場合は、さらに重要になることに注意してください。これは例えば、スパース結合インデックスの作成時に起きます。スパース結合インデックスの詳細については、<Teradata Vantage™ - データベースの設計、B035-1094>のハッシュおよび結合インデックスに関する情報と、<Teradata Vantage™ - SQLデータ定義言語-構文規則および例、B035-1144>のCREATE JOIN INDEXについての説明を参照してください。

定数述部の評価

定数述部の評価は、リクエストが解析されるときに定数のみを含む述部(列参照を含まない述部)を評価します。例えば、次の複雑な述部について考えてみます。

        t1.pi=t2.pi
     OR ‘a’ IN (‘b’,‘c’)

システムは、定数述部を特定および評価し、次に述部をTRUEまたはFASEの結果に置き換えます。

Teradata Databaseがリクエストを解析するときにこの例のIN述部はFALSEと評価され、クエリー リライトにより次のように変換されます。

     t1.pi=t2.pi

ドメイン ベースの簡略化

ドメイン ベースの簡略化は、基になる列のドメイン範囲を使用して述部を簡略化します。例えば、次のテーブル定義があるとします。

     create table t1 (a1 smallint)

このテーブル定義では、定数64000が値のSMALLINT範囲内にないため、述部a1 = 64000は実現不可能になります。

     a1 = 64000 => FALSE

同様に、次の述部について考えてみます。

     a1 in (32800, 80000, 1, 2, 3)

この述部は、制約32800および80000が値のSMALLINT範囲内にないため、次のように簡略化することができます。

     a1 in (1, 2, 3)

制約ベースの簡略化のチェック

制約ベースの簡略化のチェックは、ドメイン ベースの簡略化と似ていますが、基になる列の範囲は列に指定されているチェック制約に基づいています。例えば、次のテーブル定義があるとします。

     create table t1 (a1 int NOT NULL check (a1 < 10))

このテーブル定義では、述部がチェック制約に基づく値の許可される範囲外にあるため、次の述部は実現不可能になります。

     a1 > 30 => FALSE

単一テーブル述部の統合

クエリー リライトは、重複条件または冗長条件を排除するために、単一テーブル述部を評価して書き換えます。例えば、次の述部セットについて考えてみます。

     a1 NOT IN (1,3) AND
     a1 <4 AND
     a1 >= 2

a1がINTEGER列である場合、これらの述部は次のように簡略化できます。

     a1=2

同様に、次の述部について考えてみます。

     a1 IN (1, 3, 5, 7, 9) AND
     a1 > 4

a1はINTEGER列です。

述部は次のように簡略化されます。

     a1 IN (5,7,9)

単一テーブル述部の統合により、最適化ルーチンは冗長述部の実行を排除すると同時に、より正確に選択性の見積もりを計算することができます。

クエリー リライトは、PERIOD列のBEGINおよびEND境界関数の単一テーブル述部の簡略化もサポートします。

例えば、BEGIN範囲関数に基づく次の述部について考えます。

         BEGIN(b)>DATE ‘2005-02-03’ AND
         BEGIN(b)>DATE ‘2010-02-03’

クエリー リライトは、これを次の述部に簡略化します。

     BEGIN(b)>=DATE ‘2010-02-04’

同様に、END範囲関数に基づく次の述部について考えます。

         END(b)< DATE‘2005-02-03’ AND
         END(b)< DATE‘2010-02-03’

クエリー リライトは、これを次の述部に簡略化します。

     END(b)<= DATE‘2005-02-02’

単一テーブル述部の統合は、次のように実現不可能となることがあります。

         a1 NOT IN (1, 2, 3) AND
         a1>=1 AND
         a1<=3

a1がINTEGER列の場合、上記の条件は重複せず、述部は次のように書き換えられます。

     0=1

0=1はFALSEと評価されます。

その他の場合、述部は、次のように可能値一式を制約しない述部に簡略化することができます。

        a1>1 OR a1<2 

述部は次のように書き換えできます。

     a1 IS NOT NULL

複雑な例として、次の述部について考えてみます。

     (a1 >= 1 AND a1 <= 3) OR
     (a1 >= 4 AND a1 <= 10)

a1がINTEGER列の場合、述部は次のように書き換えることができます。

     a1 >= 1 AND a1 <= 10

定数の移動

定数の移動の書き換え方法により、述部の選択性をより正確に見積もり、最適化ルーチンで広範にインデックスを使用できるようになります。次の形式から述部を書き換えるために、ブール比較演算子のいずれかの側から別の側に定数の移動が試行されます。

     <column> <±> <constant_1> <comparison_operator><constant_2>

定数の移動は、上記の形式の述部を、次の形式の述部に書き換えます。

     <column> <comparison_operator> <constant_3>

書き換え方法は、述部の列側からプラスまたはマイナス操作を削除し、その否定を述部の定数のみの側に追加することで、定数の移動を行ないます。その後、定数式は組み合わされます。折り重ねるときにオーバーフローやアンダーフローなどのエラーが発生すると、元の式を使用できるように書き換えが拒否されます。

この変換は、プラスおよびマイナスの算術演算子の場合にのみ行なわれます。

例えば、a1 + 1 > 4に書き換えられるa1>3について考えてみます。

移動される定数式は、DATE操作のINTERVAL式でもありえます。

例えば、次の述部があるとします。

     date_col + INTERVAL '3' MONTH <= '2007-03-31'

定数の移動を使用すると、この述部は次のように書き換えることができます。

     date_col <= '2006-12-31'

定数置換

定数置換リライトは、列の値が使用可能な場合にそれらを置き換え、可能な場合に実現不可能を派生しようとするか、述部を簡略化しようとします。次の形式の述部は、可能な場合にcolumn_1およびcolumn_2の値を置き換えることによって簡略化されます。

     <column_1> <±> <constant_1> <comparison_operator>
     <column_2> <±> <constant_2> 

例として、以下の述部があるとします。

     a = 10 AND
     b = 20 AND
     a + 2 = b + 1

aの値10およびbの値20を置き換えると、述部は12 = 21に簡略化され、FALSEになります。

さらに別の例として、a > a + 1に簡略化されるFALSE、およびa >= a - 1に書き換えられるa >= a - 1について考えてみます。

分散による簡略化

この分散リライトによる簡略化は、分散プロパティを使用することにより、複雑なAND/OR述部を簡略化しようとします。

以下の述部を考えてみてください。

     a > 5 AND b < 6 AND (a < 2 OR b > 9)

ANDをORブランチに分散することにより、述部は次のように簡略化できます。

     a > 5 AND b < 6 AND ((a > 5 AND a < 2) OR (b < 6 AND b > 9)) =>
     a > 5 AND b < 6 AND ( FALSE OR FALSE) =>
     a > 5 AND b < 6 AND FALSE =>
     FALSE

共通述部の因数分解

共通述部の因数分解は、分散プロパティに基づく、もう1つのリライトです。複雑なAND/OR述部に、AND/ORブランチ全体にわたる共通の述部がいくつかある場合、これらの共通述部は因数分解して述部を簡略化することができます。

以下の述部を考えてみてください。

     (a1 = 1 AND b1 = 1 AND c1 = 1) OR
     (a1 = 1 AND b1 = 1 AND d1 = 1) OR
     (a1 = 1 AND e1 = 1)

(a1 = b1 AND b1 = 1)はOR述部全体の最初の2つのブランチに共通していることに注意してください。因数分解の最初のステップで、(a1 = b1 AND b1 = 1)を因数分解すると、次の同等の述部が得られます。

     (a1 =1 AND b1 = 1 AND (c1 = 1 OR d1 = 1)) OR
     (a1 = 1 AND e1 = 1)

最初のステップの後、OR述部の残りの2つのブランチで(a1 = 1)が共通していることに注意してください。因数分解の2つ目のステップで、(a1 = 1)を因数分解すると、次の同等の述部が得られます。

     a1 = 1 AND ((b1 = 1 AND (c1 = 1 OR d1 = 1)) OR e1 = 1)

包含に基づく簡略化

包含に基づく簡略化は、集合代数の集合包含プロパティを使用して、複雑なAND/OR述部を簡略化しようとします。包含リライト ルールには、OR包含ルールとAND包含ルールの2種類があります。

OR包含ルールは次のとおりです。

     If A contains A',
        A OR (A' AND ..) => A

例えば、a > 5 OR (a > 7 AND b < 6)は、a > 5に簡略化できます。

AND包含ルールは次のとおりです。

     If A' contains A,
        A AND (A' OR ..) => A

例えば、a < 10 AND (a < 12 OR b < 6)は、a < 10に簡略化できます。

重複した述部の削除

重複した述部の削除は、同じ論理積、非論理積、またはこれらの両方をANDおよびOR述部から削除します。述部あたりの比較される重複した論理積および非論理積の最大数は、100です。