2013-06-20 4 views
0

Я хочу отправить массовое письмо своим пользователям сайта, и электронное письмо будет отправлено, чтобы сказать 100k + пользователям за раз. То, что я хочу достичь, - это сохранить записи моих вызовов mail(), т. Е. Как только почта будет отправлена ​​пользователю, запись добавляется для этого пользователя во временную таблицу. Это помогает мне в состоянии, если мой сервер падает, тогда я могу отправить электронные письма остальным пользователям.Нужно оптимизировать MySQL-запрос для оператора IN

Вот моя проблема:

Я выбираю запись из таблицы пользователей, где записи NOT IN (select sent_ids from temp_table)

Если есть на количество переданных идентификаторов, скажем, 70% от общего числа пользователей, то это сделает запрос относительно медленный.

Что делать, чтобы решить мою проблему?

+0

Я вижу, что большинство из вас предпочитает присоединиться, но мой коллега не согласен с этим. Он предпочел, чтобы максимальные электронные письма отправлялись до 10 раз в день, поэтому он думает, что мы должны добавить 10 столбцов для него в таблицу users. Поэтому, как только электронное письмо отправляется конкретному пользователю, его поле is_sent должно быть установлено в 1 для электронной почты (номер электронной почты дня, скажем, электронный номер 1). Считаете ли вы, что это самый быстрый способ, чем все другие решения? И должен ли я следовать этому или нет? –

+0

Это пахнет плохим дизайном для меня, я, конечно же, не последую этому. Это сильно изнасиловает шаблоны проектирования баз данных ИМХО. И даже если бы это было быстрее, оно вводило много других проблем и проблем с возможностью перенастройки, это не стоит. –

+0

Ну, он говорит, что проблема с IN заключается в том, что он столкнулся с проблемами сбоя сервера, потому что, как только записи слишком велики, запрос начинает задерживаться так долго, и сервер выходит из строя. Я в замешательстве: s –

ответ

1

Он не должен быть медленнее, чем другие варианты, поскольку в большинстве случаев MySQL будет максимально оптимизировать предложения IN (по крайней мере, более поздние версии). Тем не менее, вы можете попробовать LEFT JOINing temp table по id, а затем проверить send_id IS NULL, чтобы получить пользователей, которых вы еще не отправили.

1

Два варианта:

  1. Более новые версии MySQL (5.6 или MariaDB 5.5), должны иметь дело с этим запросом гораздо лучше https://blog.mozilla.org/it/2013/01/29/in-subqueries-in-mysql-5-6-are-optimized-away/
  2. Вы можете использовать JOIN заявление: SELECT, пользователи/* от пользователей РЕГИСТРИРУЙТЕСЬ TempTable ON send_id = user_id
1

Похоже, работа для внешнего соединения:

SELECT * FROM users u 
LEFT JOIN temp_table t 
    ON u.id = t.id 
WHERE t.id IS NULL 

В этом списке перечислены все пользователи, которым не было отправлено электронное письмо.

Смежные вопросы