In Query 3, stai praticamente eseguendo una sottoquery per ogni riga di mybigtable contro se stessa.
Per evitare ciò, è necessario apportare due importanti modifiche:
PRINCIPALE CAMBIAMENTO # 1: Rifattorizza la query
Ecco la tua query originale
Select count(*) as total from mybigtable
where account_id=123 and email IN
(select distinct email from mybigtable where account_id=345)
Potresti provare
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;
o forse il conteggio per email
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;
PRINCIPALE CAMBIAMENTO N. 2: indicizzazione corretta
Penso che tu lo abbia già da quando Query 1 e Query 2 funzionano velocemente. Assicurati di avere un indice composto su (account_id, email). Fai SHOW CREATE TABLE mybigtable\G
e assicurati di averne uno. Se non lo possiedi o se non sei sicuro, crea comunque l'indice:
ALTER TABLE mybigtable ADD INDEX account_id_email_ndx (account_id,email);
AGGIORNAMENTO 2012-03-07 13:26 EST
Se vuoi fare un NOT IN (), cambia INNER JOIN
in a LEFT JOIN
e controlla che il lato destro sia NULL, in questo modo:
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;
AGGIORNAMENTO 2012-03-07 14:13 EST
Si prega di leggere questi due link su come effettuare JOIN
Ecco un ottimo video di YouTube in cui ho imparato a rispondere alle domande e al libro su cui era basato