Альтернатива NOT IN на MySQL

У меня есть запрос

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

Выполнение ч / б занимает слишком много времениTransaction_Register Таблица содержит миллионы записей. Есть ли альтернатива вышеуказанному запросу? Я буду благодарен вам, ребята, если таковые имеются.

 Aron04 июн. 2013 г., 04:24
@ Джодрелл не совсем. Смысл MariaDB в том, что это MySQL. Это форк от оригинальных разработчиков MySQL из ветки Oracle. Таким образом, это ответ на вопрос MySQL. Факт никто из примечаний на самом деле не использует Oracle MySQL. FB использует свой собственный форк, Twitter поддерживает свой собственный форк, и оба они подают в открытый исходный код MariaDB, который поддерживает Wikipedia. Официальная рекомендация FB - использовать MariaDB.
 Jodrell03 июн. 2013 г., 19:00
@ Арон, но вопрос о MySql. Если вы хотите изменить двигатели, есть много вариантов.
 Jodrell03 июн. 2013 г., 18:55
@Aron SQL существует уже давно, есть много движков на выбор с различными функциями и затратами. Если вы положите какашку на лопату или золотую тарелку, она все равно плохо пахнет.
 Jodrell03 июн. 2013 г., 18:49
Вы хотите что-то быстрее, у вас есть лучшая альтернатива? Каковы схемы таблиц, как распределяются данные (статистика), есть ли у вас план выполненияEXPLAIN? Какие у вас есть счета?
 Gimmy03 июн. 2013 г., 18:55
Попробуйте добавить индекс к вашей таблице.
 Aron03 июн. 2013 г., 18:52
замените ваши двоичные файлы MySQL на MariaDb. Это намного лучше, чем MySQL для такого рода запросов. Причина в том, что он имеет гораздо лучший планировщик запросов.
 Jodrell03 июн. 2013 г., 19:11
возможный дубликатMySQL "НЕ В" запрос
 Taryn03 июн. 2013 г., 20:06
Есть ли у вас индексы на этих таблицах?
 Aron03 июн. 2013 г., 18:58
@Jodrell Что именно ты комментировал? Стоимость каждого оператора SQL различна для каждого механизма БД. MySQL известен тем, что не может эффективно использовать подзапросы.

Ответы на вопрос(2)

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 с демоверсией

 Jodrell03 июн. 2013 г., 19:07
@Jodrell после исследования, это работает лучше +1.
 Jodrell03 июн. 2013 г., 19:03
серьезный вопрос. Это дает лучшую производительность на MySQL?
 mmr19 сент. 2013 г., 10:30
спасибо за это. очень помог мне

Я сомневаюсь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 не использует индекс

LOGIC

(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 шагов

Ваш ответ на вопрос