sql >> Databáze >  >> RDS >> Mysql

Proč je tento dotaz mysql (s nulovou kontrolou) tak pomalejší než tento druhý?

Překvapuje mě, že obojí je rychlé. Navrhoval bych je nahradit výrazem 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);

A za druhé:

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

Pro oba tyto indexy chcete dva indexy:ips_fatura(ips_usuario_id) a ips_fatura(ips_usuario_id_titular) . Můžete zkontrolovat vysvětlení a ujistit se, že EXISTS používá index. Pokud ne, novější verze MySQL používají indexy pro 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);

V obou případech (EXISTS nebo IN ) cílem je udělat „semi-join“. To znamená pokutovat pouze první řadu zápalkou, nikoli všechny zápasy. To je důležitá efektivita, protože to umožňuje dotazu vyhnout se odstranění duplicit.

Spekuloval bych, že problém je v optimalizaci or -- obvykle to má za následek neefektivní JOIN algoritmy. Možná je však MySQL ve vašem prvním případě chytrá. Ale přidání IS NULL k vnějšímu stolu to odhodí.




  1. mySQL - Vložení do tří tabulek

  2. Převést hodnotu mysql LONGTEXT na hodnotu VARCHAR?

  3. Jak nakonfigurovat postgresql poprvé?

  4. Mysql se nespustí - ibdata1 je poškozen? - chyba operačního systému číslo 13 - problém s oprávněními