2013-12-10 2 views
0

У меня возникают проблемы с медленным запросом MySQL. Для каждого из них требуется более 10 минут. Я попытался переписать его с помощью LEFT JOINT, но «суставы» не являются моим лучшим опытом))MySQL, 'WHERE NOT IN' slow

Я надеюсь, что кто-то сможет мне помочь.

select subscriberId 
    from segments 
    where (segmentId = 29) 
    and subscriberId not in 
    (select subscriberId from que where (campaignId = 31 or campaignId = 32)) 
    order by rand() 
    limit 20000 

Все индексы на месте. Заранее большое спасибо.

+0

подзапросом может быть проблема пусть смотрят объяснить –

+0

Да , подзапросом является проблема. Я понимаю. Он запускает миллионы подзапросов для получения результатов. Его 100% ясны для меня. Так что я спрашиваю, как его оптимизировать) – Sergey

ответ

0

Я думаю, ваша проблема в

order by rand() 

попытки удалить это и посмотреть время.

UPDATE индекс

  1. добавить:

    alter table que добавить индекс (subscriberId)

  2. попробовать это:

    select segments.subscriberId from segments left join que on que.subscriberId = segments.subscriberId and (que.campaignId = 31 or que.campaignId = 32) where segments.segmentId = 29 and que.id is null limit 20000

Я вижу 0.08 сек и 0.13 с заказом rand().

Не используйте phpmyadmin для проверки, потому что у него больше времени на визуализацию результата. Я использую клиент MySQL консоли

20000 rows in set (0.13 sec)

mysql> select segments.subscriberId from segments left join que on que.subscriberId = segments.subscriberId and (que.campaignId = 31 or que.campaignId = 32) where segments.segmentId = 29 and que.id is null order by rand() limit 20000 ;

+0

Да, заказ от rand() не самый быстрый, однако ранее мы не «вырезали» «не в», и обычно это заняло около 1-2 секунд, что нормально , поскольку он работает в фоновом режиме. Поскольку система обновляется, и нам нужно предложить больше, нам нужно иметь более подробную сегментацию, которую мы добавили «не в», и она начала принимать «годы» для обработки – Sergey

+0

. Заказ от rand does'nt использует индексы, создает таблицы tmp и с некоторым весом файлов данных. Это действительно очень медленно. – BaBL86

+0

И мне жаль, что я не могу удалить заказ rand(), но мне нужно сохранить эту функциональность. В этом примере мне нужно выбрать 20k строк из 600k, поэтому очень важно иметь некоторое вращение. – Sergey

1

Попробуйте использовать соединение

SELECT sg.subscriberId 
    FROM segments sg JOIN que q 
    ON (sg.subscriberId = q.subscriberId and sg.segmentId = 29) 
    WHERE (q.campaignId <> 31 AND q.campaignId <> 32) 
+0

6.19 sec AWESOME, большое спасибо – Sergey

+0

На самом деле он возвращает значения, указанные в таблице queerId, которые находятся в таблице que, но мне нужно отключить эти значения :( – Sergey

+0

Можете ли вы попробовать this.I отредактировал запрос –

1

Попробуйте заменить NOT IN с NOT EXISTS

select s.subscriberId 
from segments s 
where (s.segmentId = 29) 
and NOT EXISTS (select * from que q 
       where s.subscriberId = q.subscriberId AND 
       (q.campaignId = 31 or q.campaignId = 32)) 
order by rand() 
limit 20000 
+0

10 мин - 8 сек :( – Sergey