1

したがって、この連絡先管理システムを構築しているとしましょう。USERテーブルとCONTACT_INFOテーブルがあります。すべてのユーザーに対して、0個以上のCONTACT_INFOレコードを持つことができます。私が定義した方法では、CONTACT_INFOテーブルに、関連するUSERレコードを指す外部キーを設定しました。

CONTACT_INFOレコードを持たないすべてのUSERレコードを検索したいと思います。

私はこれができることを期待しています:

SELECT * FROM user u WHERE u.user_id NOT IN (SELECT DISTINCT c.user_id FROM CONTACT_INFO);

私の懸念は、テーブルが大きくなるにつれて、このクエリのパフォーマンスが大幅に低下する可能性があることです。

私が遊んでいるアイデアの1つは、USERテーブルにCONTACT_INFOレコードがあるかどうかを示す列を追加することです。また、CONTACT_INFOにレコードを挿入するときに、DBMSがレコードが存在することを確認する必要がある場合、確認のためにそのレコードにすでにアクセスしているので、CONTACT_INFOレコードを更新するときに更新するべきではないのではないかと思いました。コストがかかり、パフォーマンスの面で。

いつものように、フィードバックは大歓迎です。

4

4 に答える 4

3

最も簡単な方法は次のとおりです。

SELECT (...) 
FROM user u
LEFT OUTER JOIN CONTACT_INFO c
ON u.user_id = c.user_id
WHERE c.user_id IS NULL

より扱いにくく見えますが、より適切にスケーリングする必要があります。

于 2009-06-15T22:39:17.010 に答える
2

私のテストから、次の方法は BradC の方法よりも高速です。

select (...)
from user u
where not exists (select null from CONTACT_INFO c where u.user_id = c.user_id)

これは、コンパイラが変換自体を行う必要があるためかもしれませんが、わかりません。

ただし、ル・ドルフィエは原則として正しいです。データベースに直接インデックスを設定した場合 (つまり、両方の user_id 列にインデックスを作成する必要があります)、レコードの数に関係なく、ここでの回答とこれらの応答のほとんどは非常に高速になります。あなたのデータベースに持っています。

ちなみに、「HasContactInfo」ブール値とともにユーザーを一覧表示するクエリを取得する方法を探している場合は、次のようにすることができます。

select u.(...), 
  (case when exists (select null from CONTACT_INFO c where c.user_id = u.user_id) then 1
        else null
        end) has_contact_info
from user u

この 2 番目の解決策は、あなたの場合には役に立たないかもしれませんが、自動的に最適化されると想定していたいくつかの単純なクエリよりもはるかに高速であることがわかりました。

于 2009-06-15T23:00:34.337 に答える
1

パフォーマンスが低下すると考える理由はありますか? これは、SQL で最も効率的なクエリ タイプの 1 つです。ただし、DISTINCT は削除してください。

于 2009-06-15T22:39:58.273 に答える
1

少なくともオラクルでは、次を使用してパフォーマンスを向上させます

ここで 0 = (CONTACT_INFO c から count(*) を選択...)

NOT IN 句の代わりに。

于 2009-06-15T23:47:35.067 に答える