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の全テーブルスキャンが実行されます。全表スキャンを避けたい。
このクエリを書き換えてすばやく実行するにはどうすればよいですか?どのインデックスを使用する必要がありますか?
select tableA.id from tableA left outer join tableB on (tableA.id = tableB.id)
where tableB.id is null
order by tableA.id desc
データベースがインデックスの交差を行う方法を知っている場合、これは主キーインデックスのみに影響します
left join
よりも高速な場合があるため、exists
も使用できます。どのベンチマークを使用するかを判断するには、ベンチマークを行う必要があります。
select
id
from
tableA a
where
not exists
(select 1 from tableB b where b.id = a.id)
exists
がleft join
よりも効率的であることを示すために、SQL Server 2008でのこれらのクエリの実行計画を以下に示します。
left join
-サブツリーの合計コスト:1.09724:
exists
-サブツリーの総コスト:1.07421:
TableBのすべてのIDに対してtableAのすべてのIDを確認する必要があります。完全な機能を備えたRDBMS(Oracleなど)は、それをINDEX FULL FAST SCANに最適化でき、テーブルにはまったく触れません。 H2のオプティマイザーがそれほどスマートかどうかはわかりません。
H2はMINUS構文をサポートしているため、これを試してください
select id from tableA
minus
select id from tableB
order by id desc
より高速に実行される可能性があります。確かにベンチマークする価値があります。
私の小さなデータセットの場合、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;
これらのメソッドのどれがH2に最適であるか(またはすべてが機能する場合でも)を言うことはできませんが、TSQLで使用可能なすべての(良い)メソッドを詳述する記事を書きました。あなたは彼らに一撃を与え、それらのどれかがあなたのために働くかどうか見ることができます:
select parentTable.id from parentTable
left outer join childTable on (parentTable.id = childTable.parentTableID)
where childTable.id is null