В Query 3 вы в основном выполняете подзапрос для каждой строки mybigtable против себя.
Чтобы этого избежать, нужно внести два основных изменения:
ОСНОВНОЕ ИЗМЕНЕНИЕ № 1: Рефакторинг запроса
Вот ваш оригинальный запрос
Select count(*) as total from mybigtable
where account_id=123 and email IN
(select distinct email from mybigtable where account_id=345)
Вы могли бы попробовать
select count(*) EmailCount from
(
select tbl123.email from
(select email from mybigtable where account_id=123) tbl123
INNER JOIN
(select distinct email from mybigtable where account_id=345) tbl345
using (email)
) A;
или, может быть, количество на электронную почту
select email,count(*) EmailCount from
(
select tbl123.email from
(select email from mybigtable where account_id=123) tbl123
INNER JOIN
(select distinct email from mybigtable where account_id=345) tbl345
using (email)
) A group by email;
ОСНОВНОЕ ИЗМЕНЕНИЕ № 2: Правильная индексация
Я думаю, у вас уже есть, так как Query 1 и Query 2 работают быстро. Убедитесь, что у вас есть составной индекс (account_id, email). Сделайте SHOW CREATE TABLE mybigtable\G
и убедитесь, что у вас есть. Если у вас его нет или вы не уверены, то все равно создайте индекс:
ALTER TABLE mybigtable ADD INDEX account_id_email_ndx (account_id,email);
ОБНОВЛЕНИЕ 2012-03-07 13:26 EST
Если вы хотите сделать NOT IN (), измените на INNER JOIN
a LEFT JOIN
и проверьте, что правая сторона имеет значение NULL, например:
select count(*) EmailCount from
(
select tbl123.email from
(select email from mybigtable where account_id=123) tbl123
LEFT JOIN
(select distinct email from mybigtable where account_id=345) tbl345
using (email)
WHERE tbl345.email IS NULL
) A;
ОБНОВЛЕНИЕ 2012-03-07 14:13 EST
Пожалуйста, прочитайте эти две ссылки на участие
Вот отличное видео на YouTube, где я научился проводить рефакторинг запросов и книгу, на которой он основан