質問があります
SELECT DISTINCT phoneNum
FROM `Transaction_Register`
WHERE phoneNum NOT IN (SELECT phoneNum FROM `Subscription`)
LIMIT 0 , 1000000
実行に時間がかかりすぎる b/cTransaction_Register
テーブルには何百万ものレコードがあります 上記のクエリの代替手段はありますか? もしあれば、皆さんに感謝します.
別の方法は、LEFT JOIN を使用することです。
select distinct t.phoneNum
from Transaction_Register t
left join Subscription s
on t.phoneNum = s.phoneNum
where s.phoneNum is null
LIMIT 0 , 1000000;
デモで SQL Fiddle を参照してください
LEFT JOIN
本当に よりも優れたパフォーマンスを発揮するかどうかは疑問ですNOT IN
。次のテーブル構造でいくつかのテストを実行するだけです (間違っている場合は修正してください)。
account (id, ....) [42,884 rows, index by id]
play (account_id, playdate, ...) [61,737 rows, index by account_id]
(1) クエリLEFT JOIN
SELECT * FROM
account LEFT JOIN play ON account.id = play.account_id
WHERE play.account_id IS NULL
(2) でクエリNOT IN
SELECT * FROM
account WHERE
account.id NOT IN (SELECT play.account_id FROM play)
LIMIT 0、...での速度テスト
LIMIT 0,-> 100 150 200 250
-------------------------------------------------------------------------
LEFT 3.213s 4.477s 5.881s 7.472s
NOT EXIST 2.200s 3.261s 4.320s 5.647s
--------------------------------------------------------------------------
Difference 1.013s 1.216s 1.560s 1.825s
上限を上げていくと差がどんどん大きくなっていく
EXPLAIN
(1) クエリLEFT JOIN
SELECT_TYPE TABLE TYPE ROWS EXTRA
-------------------------------------------------
SIMPLE account ALL 42,884
SIMPLE play ALL 61,737 Using where; not exists
(2) でクエリNOT IN
SELECT_TYPE TABLE TYPE ROWS EXTRA
-------------------------------------------------
SIMPLE account ALL 42,884 Using where
DEPENDENT SUBQUERY play INDEX 61,737 Using where; Using index
LEFT JOIN はインデックスを使用していないようです
(1) クエリLEFT JOIN
アカウントとプレイの間の LEFT JOIN の後、42,884 * 61,737 = 2,647,529,508 行が生成されます。次に、これらの行で play.account_id が NULL かどうかを確認します。
(2) でクエリNOT IN
二分探索は、アイテムの存在に log2(N) を取ります。つまり、42,884 * log2(61,737) = 686,144 ステップです。