1

JOIN条件でリンクする必要があるいくつかの同一のフィールドを持つ2つのテーブルがあります。たとえば、各テーブルにはP1、P2のフィールドがあります。次の結合クエリを記述したいと思います。

SELECT ... FROM Table1
   INNER JOIN
   Table2
      ON    Table1.P1 = Table2.P1
         OR Table1.P2 = Table2.P2
         OR Table1.P1 = Table2.P2
         OR Table1.P2 = Table2.P1

私が巨大なテーブルを持っている場合、このリクエストは多くの時間を実行しています。

1つの条件のみでクエリのリクエストがどのくらいの期間になるかをテストしようとしました。まず、P2とP1のすべてのデータが新しい行としてTable1とTable2にコピーされるように、テーブルを変更しました。だから私のクエリは簡単です:

SELECT ... FROM Table1 INNER JOIN Table2 ON Table1.P = Table2.P

その結果はさらに驚きました。何時間にもわたる実行時間(最初のケース)が2〜3秒に短縮されました。

どうしてそんなに違うの?複雑な条件が常にパフォーマンスを低下させるということですか?どうすれば問題を改善できますか?P1、P2インデックスが役立つかもしれませんか?最初のDBスキーマのままにし、1つのフィールドPに移動したくない。

4

3 に答える 3

4

クエリが異なる理由は、オプティマイザによって使用される結合戦略のためです。2 つのテーブルを結合するには、基本的に次の 4 つの方法があります。

  1. 「ハッシュ結合」: 2 番目の値を検索するために使用するテーブルの 1 つにハッシュ テーブルを作成します。
  2. 「マージ結合」: 両方のテーブルをキーでソートし、結合の結果を順番に読み取ります。
  3. 「インデックス検索」: インデックスを使用して、1 つのテーブル内の値を検索します。
  4. 「ネストされたループ」: 各テーブルの各値を他のテーブルのすべての値と比較します。

(そして、これらには、テーブルの代わりにインデックスを使用する、パーティションを操作する、複数のプロセッサを処理するなどのバリエーションがあります。) 残念ながら、SQL Server Management Studio では、(3) と (4) の両方が入れ子になったループ結合として表示されます。さらによく見ると、ノードのパラメーターとの違いがわかります。

いずれにせよ、元の結合は最初の 3 つのうちの 1 つであり、高速に処理されます。これらの結合は、基本的に「等結合」でのみ使用できます。つまり、2 つのテーブルを結合する条件に等値演算子が含まれている場合です。

単一の等式から「in」または一連の「or」条件に切り替えると、結合条件が等結合から非等結合に変更されます。私の観察では、この場合、SQL Server はお粗末な最適化を行っています (公平を期すために、他のデータベースもほとんど同じことをしていると思います)。パフォーマンスへの影響は、優れた結合アルゴリズムからネストされたループ アルゴリズムへの移行による影響です。

テストせずに、次の戦略のいくつかを提案するかもしれません.

  1. 両方のテーブルの P1 と P2 にインデックスを作成します。SQL Server は、非等結合の場合でもインデックスを使用する場合があります。
  2. 別のソリューションで提案されているユニオン クエリを使用します。各クエリは正しく最適化する必要があります。
  3. これらが 1 対 1 の結合であると仮定すると、複数の結合のセットとしてこれを行うこともできます。

    table1 t1 から t1.p1 の左外部結合 table2 t2_11 = t2_11.p1 t1.p1 の左外部結合 table2 t2_12 = t2_12.p2 t1.p2 の左外部結合 table2 t2_21 = t2_21.p2 t1 の左外部結合 table2 t2_22。 p2 = t2_22.p2

次に、SELECT で case/coalesce ロジックを使用して、実際に必要な値を取得します。これはより複雑に見えるかもしれませんが、非常に効率的です。

于 2012-09-09T23:51:06.160 に答える
2

4つのクエリとUnionの結果を使用できます

SELECT ... FROM Table1
INNER JOIN
Table2
  ON    Table1.P1 = Table2.P1
UNION
SELECT ... FROM Table1
INNER JOIN
Table2
  ON   Table1.P1 = Table2.P2
UNION
SELECT ... FROM Table1
INNER JOIN
Table2
  ON    Table1.P2 = Table2.P1
UNION
SELECT ... FROM Table1
INNER JOIN
Table2
  ON   Table1.P2 = Table2.P2
于 2012-09-09T11:30:56.243 に答える
0

CTE を使用するとパフォーマンスが向上しますか?

;WITH Table1_cte 
AS
(
SELECT 
      ...
      [P] = P1
FROM Table1
UNION   
SELECT 
      ...
      [P] = P2
FROM Table1
)
, Table2_cte 
AS
(
SELECT 
      ...
      [P] = P1
FROM Table2
UNION   
SELECT 
      ...
      [P] = P2
FROM Table2
)
SELECT ... FROM Table1_cte x
   INNER JOIN
   Table2_cte y
      ON x.P = y.P

プロセッサに関する限り、上記は同じ複雑な条件の構文が異なるだけだと思います。

于 2012-09-09T14:35:56.783 に答える