Mysql
 sql >> Base de données >  >> RDS >> Mysql

Pourquoi cette requête mysql (avec une vérification nulle) est-elle si plus lente que celle-ci ?

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.