Dans la requête 3, vous exécutez essentiellement une sous-requête pour chaque ligne de mybigtable contre elle-même.
Pour éviter cela, vous devez apporter deux modifications majeures:
CHANGEMENT MAJEUR # 1: Refactoriser la requête
Voici votre requête d'origine
Select count(*) as total from mybigtable
where account_id=123 and email IN
(select distinct email from mybigtable where account_id=345)
Tu pourrais essayer
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 peut-être le nombre par 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;
CHANGEMENT MAJEUR # 2: Indexation appropriée
Je pense que vous l'avez déjà depuis Query 1 et Query 2 fonctionnent rapidement. Assurez-vous d'avoir un index composé sur (account_id, email). Faites-en un SHOW CREATE TABLE mybigtable\G
et assurez-vous d'en avoir un. Si vous ne l'avez pas ou si vous n'êtes pas sûr, créez quand même l'index:
ALTER TABLE mybigtable ADD INDEX account_id_email_ndx (account_id,email);
MISE À JOUR 2012-03-07 13:26 EST
Si vous voulez faire un NOT IN (), changez le INNER JOIN
en a LEFT JOIN
et vérifiez que le côté droit est NULL, comme ceci:
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;
MISE À JOUR 2012-03-07 14:13 EST
Veuillez lire ces deux liens pour faire des JOIN
Voici une excellente vidéo YouTube où j'ai appris à refactoriser les requêtes et le livre sur lequel elles étaient basées