2

私は2つのテーブルを持っています:

表 A:

Name, isPair

表 B:

Name1, Name2, Status

これは私のクエリです:

SELECT Name
FROM A
LEFT JOIN B ON (A.Name = B.Name2)
WHERE A.isPair = 'T' AND (B.status <> 'valid' OR B.status IS NULL)

両方のテーブルに数百万行あります。現在のクエリ速度では、完了するまでに 3 か月以上かかります。両方のテーブルに適切にインデックスを付けました。最初に INNER JOIN を実行したとき、完了までに 10 分しかかかりませんでしたが、クエリがテーブル B の Name2 列にない行を返さないことがわかりました。これは、返される必要があるため問題でした。

4

1 に答える 1

3

このクエリは、正しい結果をより速く返す可能性があります。または、速度が改善されずに誤った結果を返す可能性があります。

これはすべて SQL Server の知識に基づいていますが、InnoDB にも同じ特性があると思います。

SELECT Name 
FROM A
WHERE A.isPair = 'T'
AND NOT EXISTS (
    SELECT 1 FROM B 
    WHERE A.Name = B.Name2
    AND B.status = 'valid'
    )

ブール論理を正しく再配置したことを願っています。

B に一致しない、またはステータスが <> 有効で一致する A のレコードを検索する前に

新しいクエリは、B で status = valid の一致を見つけることができない A からのレコードを返します。うまくいけば、それは同じことです。

ここで使用しているデータベースの概念は 2 つあります。

  1. EXISTS を使用すると、テーブル レコードが存在するかどうかを確認できます。テーブルに結合してそこから値を取得する必要はありません。ほとんどのクエリ プランナーはこれを自動的に行いますが、これはロング ショットです。

  2. <>つまり、列を含むインデックスを利用することはできませんstatus。つまり、値がない場合にインデックスを明示的に検索することはできません。特定の値のインデックスのみを検索できます。. したがって=、この理由と、NOT EXISTSロジックをサポートするため、に変更しました

繰り返しになりますが、InnoDB についてはよくわかりませんが、これらの制限がなければ、トリックは Oracle と Microsoft によってすでにコピーされていたはずです。

クエリ プランを比較すると、この書き直しによって違いが生じるかどうかがわかります。また、クエリの既存の INNER バージョンと OUTER バージョンの間でクエリ プランを比較すると、問題が明らかになる可能性があります。

于 2014-10-27T06:45:52.013 に答える