11

行の特定の識別子が他の2つのテーブルのいずれにも存在しない行のみを挿入する必要があるinsert-selectステートメントがあります。次のうちどれが速いでしょうか?

INSERT INTO Table1 (...)
SELECT (...) FROM Table2 t2
WHERE ...
   AND NOT EXISTS (SELECT 'Y' from Table3 t3 where t2.SomeFK = t3.RefToSameFK)
   AND NOT EXISTS (SELECT 'Y' from Table4 t4 where t2.SomeFK = t4.RefToSameFK AND ...)

... また...

INSERT INTO Table1 (...)
SELECT (...) FROM Table2 t2
WHERE ...
   AND t2.SomeFK NOT IN (SELECT RefToSameFK from Table3)
   AND t2.SomeFK NOT IN (SELECT RefToSameFK from Table4 WHERE ...)

...または彼らはほぼ同じように機能しますか?さらに、このクエリを構造化するために望ましい方法は他にありますか?サブクエリは、多項式係数によって実行時間を増やすクエリに別の「ディメンション」を追加するため、一般的に嫌いです。

4

4 に答える 4

12

通常、がの存在下では同等ではないため、がNOT INより遅い/速いかどうかは関係ありません。読む:NOT EXISTSNULL

NOT IN vs NOT EXISTS

NOT EXISTSこれらの場合、通常期待される動作をするため、ほとんどの場合、が必要になります。

それらが同等である場合、データベースはすでにそれを理解しており、両方に対して同じ実行プランを生成する可能性があります。

両方のオプションが同等であり、データベースがそれを理解できないいくつかのケースでは、両方の実行プランを分析し、特定のケースに最適なオプションを選択することをお勧めします。

于 2012-09-19T18:36:49.213 に答える
1

LEFT OUTER JOINを使用して、RIGHTテーブルの値がNULLかどうかを確認できます。値がNULLの場合、その行は存在しません。これは、サブクエリを回避する1つの方法です。

SELECT (...) FROM Table2 t2
LEFT OUTER JOIN t3 ON (t2.someFk = t3.ref)
WHERE t3.someField IS NULL
于 2012-09-19T18:27:43.923 に答える
1

これは、テーブルのサイズ、使用可能なインデックス、およびそれらのインデックスのカーディナリティによって異なります。

両方のクエリで同じ実行プランが得られず、どちらのクエリもサブクエリの代わりにJOINを実行する予定がない場合は、バージョン2の方が高速だと思います。バージョン1は相関しているため、さらに多くのサブクエリが生成されます。バージョン2は、合計3つのクエリで満たすことができます。

(また、異なるエンジンが一方向または別の方向にバイアスされる可能性があることに注意してください。一部のエンジンは、クエリが同じであると正しく判断し(実際同じである場合)、同じ実行プランに解決される場合があります。)

于 2012-09-19T18:34:27.527 に答える
0

より大きなテーブルの場合、IN句はテーブルのアーキテクチャに応じてサブクエリを何度も実行するため、NOT EXISTS/EXISTSを使用することをお勧めします。

コストオプティマイザーに基づく:

違いはありません。

于 2016-04-19T14:44:38.147 に答える