Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (日本語) » SQL Anywhere サーバ - SQL の使用法 » クエリ処理 » クエリの最適化と実行 » セマンティック・クエリ変形

 

サブクエリを EXISTS 述部として書き換える

SQL Anywhere の設計の基本となる仮定条件では、メモリを大事に使用し、デフォルトでできるだけ速やかにカーソルの最初の 2、3 の結果を返すことが要求されています。SQL Anywhere は、これらの目的を遂行するため、このような書き換えがセマンティック上正しい場合は、IN、ANY、SOME 述部などの集合演算サブクエリすべてを EXISTS 述部または NOT EXISTS 述部として書き換えます。これにより、SQL Anywhere は不要なワーク・テーブルを作成しないで、テーブルにアクセスするための適切なインデックスをより簡単に識別できるようになります。

非相関サブクエリと相関サブクエリ

非相関サブクエリとは、その外部クエリに含まれる 1 つまたは複数のテーブルを明示的に参照しないサブクエリです。

次の例は、非相関サブクエリを含む一般的なクエリを示しています。このクエリは、2001 年 1 月 1 日に注文していないすべての顧客に関する情報を選択します。

SELECT *
FROM Customers c
WHERE c.ID NOT IN
   (  SELECT o.CustomerID
      FROM SalesOrders o
      WHERE o.OrderDate = '2001-01-01' );

このクエリに対する考えられる評価方法の 1 つとしては、まず 2001 年 1 月 1 日に注文した、SalesOrders テーブル内のすべての顧客のワーク・テーブルを作成します。次に、Customers テーブルに問い合わせて、ワーク・テーブルにリストされている顧客ごとに 1 つのローを抽出します。

ただし、SQL Anywhere は結果をワーク・テーブルとして実体化することを避けます。また、結果の最初の 2、3 のローを最も速く返すプランを優先します。したがって、オプティマイザは、NOT EXISTS 述部を使用して、このようなクエリを書き換えます。この形式では、サブクエリが「相関」サブクエリになり、Customers テーブルの ID カラムへの明示的な外部参照を持つようになります。

SELECT *
FROM Customers c
WHERE NOT EXISTS
   (  SELECT *
      FROM SalesOrders o
      WHERE o.OrderDate = '2000-01-01'
         AND o.CustomerID = c.ID );

このクエリは、前述のクエリとセマンティック上は同等ですが、この新しい構文で表すと、次の利点が明らかになります。

  1. オプティマイザは、SalesOrders テーブルの CustomerID 属性または OrderDate 属性のインデックスを選択して使用できます (ただし、SQL Anywhere サンプル・データベースでは、ID カラムと CustomerID カラムに対してのみインデックスが作成されています)。

  2. オプティマイザは、中間結果をワーク・テーブルに実体化しないでサブクエリを評価することもできます。

  3. データベース・サーバは、実行中に相関サブクエリの結果をキャッシュできます。これにより、以前に計算されたこの述部の値を外部参照 c.ID の同じ値で再利用できます。上記のクエリの場合、顧客の ID 番号が Customers テーブル内でユニークであるため、キャッシュは役に立ちません。そのため、サブクエリは外部参照 c.ID が常に異なる値で計算されます。

サブクエリ・キャッシュの詳細については、サブクエリと関数のキャッシュを参照してください。

参照