Mysql
 sql >> база данни >  >> RDS >> Mysql

Защо тази mysql заявка (с проверка за нула) е толкова по-бавна от тази друга?

Изненадан съм, че и двете са бързи. Бих предложил да ги замените с 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);

И за второто:

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

И за двете ви трябва два индекса:ips_fatura(ips_usuario_id) и ips_fatura(ips_usuario_id_titular) . Можете да проверите обяснението, за да сте сигурни, че EXISTS използва индекса. Ако не, по-новите версии на MySQL използват индекси за 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);

И в двата случая (EXISTS или IN ) целта е да се направи "полусъединяване". Тоест да глобявате само първия ред със съвпадение, а не всички съвпадения. Това е важна ефективност, тъй като позволява на заявката да избегне премахването на дублиране.

Бих предположил, че проблемът е в оптимизацията на or -- обикновено това води до неефективно JOIN алгоритми. Въпреки това, може би MySQL е умен в първия ви случай. Но добавянето на IS NULL към външната маса го изхвърля.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да напиша миграция за промяна на първичния ключ на модела с ManyToManyField

  2. MYSQL INSERT или UPDATE IF

  3. Възстановяване на изтрития 'root' потребител и парола за MySQL

  4. PHP MYSQL - Разлика между 127.0.0.1 и localhost

  5. MySQL/SQL извлича ли първите 40 знака от текстово поле?