75

2つのテーブルの間には1:1の関係があります。テーブルBに対応する行がないテーブルAのすべての行を検索したいのですが、次のクエリを使用します。

SELECT id 
  FROM tableA 
 WHERE id NOT IN (SELECT id 
                    FROM tableB) 
ORDER BY id desc

idは、両方のテーブルの主キーです。主キーインデックスとは別に、tableA(id desc)にもインデックスがあります。

H2(Java組み込みデータベース)を使用すると、tableBの全表スキャンが実行されます。全表スキャンを避けたい。

このクエリを書き直してすばやく実行するにはどうすればよいですか?どのインデックスが必要ですか?

4

6 に答える 6

101
select tableA.id from tableA left outer join tableB on (tableA.id = tableB.id)
where tableB.id is null
order by tableA.id desc 

データベースがインデックスの交差を行う方法を知っている場合、これは主キーのインデックスにのみ影響します

于 2009-09-12T16:09:32.683 に答える
33

を使用することもできます。existsこれは、よりも高速な場合があるためleft joinです。どれを使用したいかを判断するには、それらをベンチマークする必要があります。

select
    id
from
    tableA a
where
    not exists
    (select 1 from tableB b where b.id = a.id)

existsこれがより効率的であることを示すためにleft join、SQLServer2008でのこれらのクエリの実行プランを次に示します。

left join-サブツリーの総コスト:1.09724:

左参加

exists-サブツリーの総コスト:1.07421:

存在する

于 2009-09-12T16:15:47.180 に答える
7

tableAのすべてのIDをtableBのすべてのIDと照合する必要があります。フル機能のRDBMS(Oracleなど)は、それをINDEX FULL FAST SCANに最適化して、テーブルにまったく触れないようにすることができます。H2のオプティマイザーがそれほど賢いかどうかはわかりません。

H2はMINUS構文をサポートしているので、これを試してみてください

select id from tableA
minus
select id from tableB
order by id desc

それはより速く実行するかもしれません。それは確かにベンチマークする価値があります。

于 2009-09-12T16:18:49.890 に答える
6

私の小さなデータセットの場合、Oracleはこれらのクエリのほとんどすべてに、テーブルに触れることなく主キーインデックスを使用するのとまったく同じプランを提供します。例外は、プランのコストが高いにもかかわらず、一貫した取得を少なくすることができるMINUSバージョンです。

--Create Sample Data.
d r o p table tableA;
d r o p table tableB;

create table tableA as (
   select rownum-1 ID, chr(rownum-1+70) bb, chr(rownum-1+100) cc 
      from dual connect by rownum<=4
);

create table tableB as (
   select rownum ID, chr(rownum+70) data1, chr(rownum+100) cc from dual
   UNION ALL
   select rownum+2 ID, chr(rownum+70) data1, chr(rownum+100) cc 
      from dual connect by rownum<=3
);

a l t e r table tableA Add Primary Key (ID);
a l t e r table tableB Add Primary Key (ID);

--View Tables.
select * from tableA;
select * from tableB;

--Find all rows in tableA that don't have a corresponding row in tableB.

--Method 1.
SELECT id FROM tableA WHERE id NOT IN (SELECT id FROM tableB) ORDER BY id DESC;

--Method 2.
SELECT tableA.id FROM tableA LEFT JOIN tableB ON (tableA.id = tableB.id)
WHERE tableB.id IS NULL ORDER BY tableA.id DESC;

--Method 3.
SELECT id FROM tableA a WHERE NOT EXISTS (SELECT 1 FROM tableB b WHERE b.id = a.id) 
   ORDER BY id DESC;

--Method 4.
SELECT id FROM tableA
MINUS
SELECT id FROM tableB ORDER BY id DESC;
于 2010-12-10T14:36:54.853 に答える
3

これらのメソッドのどれがH2で最適であるか(またはすべてが機能する場合でも)はわかりませんが、TSQLで使用可能なすべての(優れた)メソッドについて詳しく説明した記事を書きました。あなたは彼らにショットを与えて、それらのどれかがあなたのために働くかどうか見ることができます:

http://code.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=QueryBasedUponAbsenceOfData&referringTitle=Home

于 2009-09-12T16:17:13.340 に答える
-1
select parentTable.id from parentTable
left outer join childTable on (parentTable.id = childTable.parentTableID) 
where childTable.id is null
于 2018-07-21T11:59:00.437 に答える