冗長な結合の排除 - Advanced SQL Engine - Teradata Database

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

Product
Advanced SQL Engine
Teradata Database
Release Number
17.05
17.00
Published
2020年6月
Language
日本語
Last Update
2021-03-30
dita:mapPath
ja-JP/ykx1561500561173.ditamap
dita:ditavalPath
ja-JP/ykx1561500561173.ditaval
dita:id
B035-1142
Product Category
Software
Teradata Vantage

結合は、SQL問合わせの中でももっとも頻繁に指定される演算の1つです。さらにこれは、SQLコーダーのパレットの中でもっとも膨大なリソースを消費する演算です。結合の排除では、問合わせから不必要なテーブルが排除されます。

結合排除は、一般には以下の状況で使用されます。
  • 2つのテーブル間の何らかの形式の参照整合性に基づく内部結合。
  • 左および右の外部結合は、結合が結合指定内の右テーブルからの固有列に基づいている場合は排除可能。

どちらの場合も、問合わせ全体を保持するために排除されたテーブルからの射影は必要としないことを前提として、結合およびテーブルは問合わせから削除されます(排除されるテーブルは内部結合内の親テーブル、および外部結合の内部テーブルです)。

数多くの最適化された結合アルゴリズムによって、Teradata Databaseでは比較的容易に結合を処理できます。とはいえ、結合を削除したり、より簡略化したりできる場合は、結果のパフォーマンスは常により良いものになります。最適化ルーチンが不必要または冗長な結合を認識して排除する方法を示す最良の例は、<Teradata Vantage™ - SQLデータ操作言語、B035-1146>の「外部結合のケース スタディ」とその副見出し項に掲載されています。「最初の試行」および「3番目の試行」の項は、最適化ルーチンが貧弱に作成された結合を簡略化する方法の特に良い例です。

テーブル間のプライマリ キーと外部キーの関係は、標準化されたデータ モデルとそれに対応する物理データベースの関係に似ています。そのような関係の親テーブルをPK-tablesとして定義し、子テーブルをFK-tablesとして定義します。Teradata Databaseで、テーブルを作成または変更する際には、参照整合性制約を指定することによって、これらのリレーションシップを明示的に定義できます(<Teradata Vantage™ - SQLデータ定義言語-構文規則および例、B035-1144>の「CREATE TABLE」および「ALTER TABLE」を参照。また、<Teradata Vantage™ - データベースの設計、B035-1094>の「データベースの整合性を維持するための設計」を参照)。

プライマリ キーと外部キーの列セットに基づく結合で、PKテーブルとFKテーブルに問合わせることも一般的で、それはPK-FK結合と呼ばれています。PK-FK結合は冗長な場合があります。例えば、問合わせがPK列セット以外のPKテーブルの列を参照しない場合などです。このような冗長結合を認識して排除することにより、問合わせ実行時間を大幅に減らすことができます。

垂直パーティション化

テーブルを垂直方向にパーティション化する簡単な方法は、列パーティション テーブルとして定義することです。この方法が垂直パーティション化の第1の選択になります。また、テーブルの垂直パーティション化は、列パーティション化が不可能な場合(例えば、パーティションに異なる属性が必要なとき)にのみ使用するべきです。

2つのテーブルの間で参照整合性制約を実装できる別の応用例として、単一の幅広いテーブルにおける垂直パーティション化があります。垂直パーティション化とは、非常に多数の列があり、その多くがめったに参照されないテーブルを、頻繁にアクセスされる列を保持するテーブルと、アクセス頻度の少ない列を保持する別のテーブルに分割することを意味します。テーブル間の一貫性を維持し、すべての列内に正しいデータが含まれる一貫性のある仮想テーブルを保持するには、テーブルの間で参照整合性制約が必要になります。この場合、PKテーブルとFKテーブルの選択は任意ですが、頻繁にアクセスされる列があるテーブルをFKテーブルとして定義することをお勧めします。

この人工的なパーティション化を隠すため、PK-FK結合を使用する両方のテーブルからすべての列を選択するビューを定義できます。FKテーブルからの列のみを参照するビューに対してリクエストを実行依頼する場合、その結合は明らかに冗長であり、排除できます。クエリー リライトを介さずに、問合わせから冗長な結合を削除することはできないことに注意してください。

冗長結合の結合排除の例

次のリクエストは冗長結合を示しています。

     SELECT s.suppkey, s.address, n.nationkey
     FROM supplier AS s, nation AS n
     WHERE s.nation_key=n.nation_key
     ORDER BY n.nation_key;

このリクエスト内の結合は冗長になります。これは、supplierの各行に次の参照整合性定義に基づいて、supplierテーブルのnationと完全に一致する行が含まれているためです。

     FOREIGN KEY (nation_key) REFERENCES nation (nation_key).

また、リクエストではn_nationkeyのみが参照されます。これはs.nation_keyと置き換えることができます。結合排除後に変更されたクエリーは次のようになります。

     SELECT s.supp_key, s.address, s.nation_key
     FROM supplier
     ORDER BY s.nation_key;

PK-FK結合を排除するための条件

PK-FK結合を排除するには次の条件で十分です。また、もちろん、PKテーブルおよびすべてがこの書き換え方法によりチェックされます。
  • 2つのテーブルの間で、参照整合性制約が定義されています。
  • 問合わせ条件は接続的です。
  • リクエストでは、PK列以外のPKテーブルのどの列も参照されません。これには、SELECT、WHERE、GROUP BY、HAVING、ORDER BY、およびその他の句も含まれます。
  • WHERE句内にPK列が表示されるのは、PK=FK (等価)結合の場合のみです。

これらの4つの条件が満たされる場合、PKテーブルとPK-FK結合をリクエストから削除でき、問合わせ内のPK列に対するすべての参照が対応するFK列にマップされます。また、クエリー リライトは、FK列をnullにできる場合に、その列にNOT NULL条件を追加します。この最適化はルールとして適用されるので、コスト計算は必要ありません。また、クエリー リライトはこれらの最適化を自動的に実行します。この最適化をトリガーするには、子テーブルと親テーブルの間で参照整合性制約を定義する必要があります。

参照整合性保持のコストが、結合排除によって得られるメリットを上回る場合があることに注意してください。この可能性を軽減するため、バッチ参照整合性制約、または参照制約任意を代用できます(参照整合性の種類については、<Teradata Vantage™ - SQLデータ定義言語-構文規則および例、B035-1144>の「CREATE TABLE」および<Teradata Vantage™ - データベースの設計、B035-1094>の「データベースの整合性を維持するための設計」を参照)。

下のテーブルでは、これらの2つの参照整合性メカニズム間の相違点を概説しています。

参照整合性の種類 説明
バッチ制約 参照整合性は、関係しているテーブルの間に適用されます。

一般に、バッチ参照整合性制約を保持するコストは、標準の参照整合性制約と同じ関係を保持するコストよりも大幅に少なくなります。

参照制約 参照整合性は、関係しているテーブルの間に適用されません。

制約は、主に結合排除の際のヒントとして使用されます。

一般に、親と子の関係に一貫性があるという確信がある場合(つまり、参照整合性違反の可能性がほとんどないか、まったくない場合)にのみ、参照制約を指定します。

次のSELECTリクエストについて考えてみます。

     SELECT sales1.*
     FROM sales1, product
     WHERE sales_product_key=product_key;

テーブルは、クエリーから安全に削除できます。これは、このテーブルがsales1のディメンション テーブルであり、それに対する参照のみが、sales1とのPK-FK結合を使用しているためです。このロジックは、結合条件が内部テーブルの固有列における等価条件である場合、外部結合から内部テーブルを削除する際にも適用されます。

次の例は、外部結合の排除を示しています。

     SELECT sales1.*
     FROM sales1 LEFT OUTER JOIN product
     ON sales_product_key=product_key;