6

質問があります

SELECT DISTINCT phoneNum 
FROM `Transaction_Register` 
WHERE phoneNum NOT IN (SELECT phoneNum FROM `Subscription`) 
LIMIT 0 , 1000000

実行に時間がかかりすぎる b/cTransaction_Registerテーブルには何百万ものレコードがあります 上記のクエリの代替手段はありますか? もしあれば、皆さんに感謝します.

4

2 に答える 2

17

別の方法は、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 を参照してください

于 2013-06-03T16:51:53.247 に答える
5

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 ステップです。

于 2013-06-03T18:00:37.657 に答える