Na Consulta 3, você está basicamente executando uma subconsulta para cada linha do mybigtable contra si mesma.
Para evitar isso, você precisa fazer duas grandes alterações:
ALTERAÇÃO PRINCIPAL 1: Refatorar a consulta
Aqui está sua consulta original
Select count(*) as total from mybigtable
where account_id=123 and email IN
(select distinct email from mybigtable where account_id=345)
Você poderia tentar
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;
ou talvez a contagem por e-mail
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;
MAIOR ALTERAÇÃO # 2: Indexação Correta
Acho que você já tem isso desde que a consulta 1 e a consulta 2 são executadas rapidamente. Verifique se você tem um índice composto em (account_id, email). Faça SHOW CREATE TABLE mybigtable\G
e verifique se você tem um. Se você não o possui ou não tem certeza, crie o índice de qualquer maneira:
ALTER TABLE mybigtable ADD INDEX account_id_email_ndx (account_id,email);
UPDATE 2012-03-07 13:26 EST
Se você deseja fazer um NOT IN (), altere INNER JOIN
para a LEFT JOIN
e verifique se o lado direito é NULL, assim:
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;
UPDATE 2012-03-07 14:13 EST
Por favor, leia estes dois links sobre como fazer JOINs
Aqui está um ótimo vídeo do YouTube, onde aprendi a refatorar consultas e o livro em que ele foi baseado