Je suis surpris que l'un ou l'autre soit rapide. Je suggérerais de les remplacer par exists
:
SELECT COUNT(*)
FROM ips_usuario u
WHERE EXISTS (SELECT 1 FROM ips_fatura f WHERE u.id = f.ips_usuario_id) OR
EXISTS (SELECT 1 FROM ips_fatura f WHERE u.ips_usuario_id_titular = f.ips_usuario_id);
Et pour le second :
SELECT COUNT(*)
FROM ips_usuario u
WHERE EXISTS (SELECT 1 FROM ips_fatura f WHERE u.id = f.ips_usuario_id) OR
(u.ips_usuario_id_titular IS NOT NULL AND
EXISTS (SELECT 1 FROM ips_fatura f WHERE u.ips_usuario_id_titular = f.ips_usuario_id)
)
Pour les deux, vous voulez deux index :ips_fatura(ips_usuario_id)
et ips_fatura(ips_usuario_id_titular)
. Vous pouvez vérifier l'explication pour être sûr que EXISTS
utilise l'index. Sinon, les nouvelles versions de MySQL utilisent des index pour IN
:
SELECT COUNT(*)
FROM ips_usuario u
WHERE u.id IN (SELECT f.ips_usuario_id FROM ips_fatura f) OR
u.ips_usuario_id_titular IN (SELECT f.ips_usuario_id FROM ips_fatura f);
Dans les deux cas (EXISTS
ou IN
) le but est de faire une "semi-jointure". C'est-à-dire de n'amender que la première ligne avec une correspondance plutôt que toutes les correspondances. C'est une efficacité importante, car cela permet à la requête d'éviter la suppression des doublons.
Je suppose que le problème est l'optimisation du or
-- généralement cela se traduit par un JOIN
inefficace algorithmes. Cependant, MySQL est peut-être intelligent dans votre premier cas. Mais l'ajout du IS NULL
à la table extérieure le jette.