sql >> Database >  >> RDS >> Mysql

Waarom is deze mysql-query (met is null-controle) zo langzamer dan deze andere?

Het verbaast me dat beide snel zijn. Ik zou willen voorstellen om ze te vervangen door 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);

En voor de tweede:

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)
      )

Voor beide wilt u twee indexen:ips_fatura(ips_usuario_id) en ips_fatura(ips_usuario_id_titular) . U kunt de uitleg controleren om er zeker van te zijn dat EXISTS maakt gebruik van de index. Zo niet, dan gebruiken de nieuwere releases van MySQL indexen voor 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);

In beide gevallen (EXISTS of IN ) het doel is om een ​​"semi-join" te doen. Dat wil zeggen, om alleen de eerste rij te boeten met een wedstrijd in plaats van alle wedstrijden. Dit is een belangrijke efficiëntie, omdat het de query in staat stelt om het verwijderen van dubbele kopieën te voorkomen.

Ik zou speculeren dat het probleem de optimalisatie is van de or -- meestal resulteert dit in inefficiënte JOIN algoritmen. Misschien is MySQL in uw eerste geval echter slim. Maar de toevoeging van de IS NULL naar de buitenste tafel gooit het weg.




  1. Heeft Oracle een gefilterd indexconcept?

  2. Hoe auto_increment uit een mysql-tabel te verwijderen

  3. Een subquery schrijven met Zend DB

  4. Heeft soft_delete van Laravel een index nodig op MySQL?