Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MySQL > Оптимизация запроса not in (select ...


Автор: sanich_ 6.11.2014, 19:16
Добрый день.
Прошу помочь в оптимизации запроса:

Код

select count(distinct(t.em)) as cr from
  (select email as em from object where email<>''
   union all
   select email as em from job_list where email<>''
   union all
   select from_email as em from send_message where from_email<>\'\'
  ) as t where t.em n


Не очень быстро работает, 2.4 сек
Проблема имеено в последней выборке

Код

as t where t.em not in (SELECT email FROM send_ignore_list_email)


Вычитал что not in можно заменить на LEFT OUTER JOIN

Сделал следующее:

Код

select count(distinct(t.em)) as cr from
 (select email as em from object where email<>''
  union all
  select email as em from job_list where email<>''
  union all
  select from_email as em from send_message where from_email<>''
) as t
LEFT OUTER JOIN send_ignore_list_email ON email=t.em where email is null 



Тоже не очень быстро работает, 2.37 сек


Собственно задача из первой выборки email вычесть вторую выборку email
Помогите пожалуйста

Автор: Akina 6.11.2014, 22:27
Индексов нехватает имхо. Но всё равно это хреновый запрос - подзапрос льётся во временную таблицу, фуллскан, все дела.. Кстати, если вместо UNION ALL использовать UNION - можно выкинуть DISTINCT. На скорость почти не повлияет, впрочем.

Автор: sanich_ 7.11.2014, 04:09
Цитата(Akina @ 6.11.2014,  22:27)
Индексов нехватает имхо. Но всё равно это хреновый запрос - подзапрос льётся во временную таблицу, фуллскан, все дела.. Кстати, если вместо UNION ALL использовать UNION - можно выкинуть DISTINCT. На скорость почти не повлияет, впрочем.

Чуток оптимизировал до вида:

Код

SELECT count(t.em) as cr
FROM 
(select email as em from object where email<>''
 union
 select email as em from job_list where email<>''
 union
 select from_email as em from send_message where from_email<>''
) as t
LEFT JOIN send_ignore_list_email as s ON t.em = s.email
WHERE s.email IS NULL



Стал выполнятся за 1.8 сек, а было 2.4 сек.
Но всеравно не быстро

Теперь
Код


EXPLAIN
SELECT count(t.em) as cr
FROM 
(select email as em from object where email<>''
 union
 select email as em from job_list where email<>''
 union
 select from_email as em from send_message where from_email<>''
) as t
LEFT JOIN send_ignore_list_email as s ON t.em = s.email
WHERE s.email IS NULL



Показывает следующее:

http://SSMaker.ru/1e23b31a/

Автор: Akina 7.11.2014, 08:55
Цитата(sanich_ @  7.11.2014,  05:09 Найти цитируемый пост)
Стал выполнятся за 1.8 сек, а было 2.4 сек.

Правильно, потому что накопление и сортировка заменились сортировкой при слиянии.

Цитата(sanich_ @  7.11.2014,  05:09 Найти цитируемый пост)
все равно не быстро

Быстрее не будет. Смирись.
Либо измени структуру БД. Объяви email отдельной сущностью, выволоки в отдельную таблицу, а в таблицах object, job_list, send_message и send_ignore_list_email соответственно FK на неё. Не полетит, конечно, но разика в три ускорится.

Добавлено через 1 минуту и 2 секунды
Цитата(sanich_ @  7.11.2014,  05:09 Найти цитируемый пост)
Показывает следующее:

Присоединяйте скрины к сообщению. Ссылки наружу - не лучшая практика. А EXPLAIN можно вообще цитировать с консоли.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)