Mysql
 sql >> Baza danych >  >> RDS >> Mysql

JOIN vs. WHERE:Dlaczego dwa zapytania, które uzyskują identyczne wyniki, wykazują 3-4 rzędy różnicy w wydajności?

MySQL ma znane problemy z optymalizacją zapytań obejmujących skorelowane podzapytania lub podselekcje. Aż do wersji 5.6.5 nie materializuje podzapytań, jednak zmaterializuje tabelę pochodną używaną w łączeniu.

W istocie oznacza to, że kiedy używasz złączenia, przy pierwszym napotkaniu podzapytania MySQL wykona następujące czynności:

SELECT code1 FROM myTable GROUP BY code1 HAVING COUNT(code1) > 1

I przechowuj wyniki w tabeli tymczasowej (która jest zaszyfrowana, aby przyspieszyć wyszukiwanie), a następnie dla każdej wartości w myTable przeszuka tabelę tymczasową, aby sprawdzić, czy kod tam jest.

Jednak od kiedy używasz IN podzapytanie nie jest zmaterializowane i jest przepisywane w następujący sposób:

SELECT t1.code1, t1.code2
FROM myTable t1
WHERE EXISTS
    (   SELECT t2.code1 
        FROM myTable t2
        WHERE t2.Code1 = t1.Code1
        GROUP BY t2.code1 
        HAVING COUNT(t2.code1) > 1
    )

Co oznacza, że ​​dla każdego code w myTable , ponownie uruchamia podzapytanie. Co w przypadku bardzo wąskiego zapytania zewnętrznego jest w porządku, ponieważ bardziej wydajne jest uruchomienie podzapytania tylko kilka razy, niż uruchomienie go dla wszystkich wartości i przechowywanie wyników w tabeli tymczasowej, jednak gdy zapytanie zewnętrzne jest szerokie, skutkuje w wewnętrznym zapytaniu wykonywanym wiele razy i tutaj pojawia się różnica w wydajności.

Więc jeśli chodzi o liczbę wierszy, zamiast uruchamiać podzapytanie ~30 000 razy, uruchamiasz je raz, a następnie wyszukujesz ~30 000 wierszy w zaszyfrowanej tabeli tymczasowej zawierającej tylko 400 wierszy. Stanowiłoby to tak drastyczną różnicę w wydajności.

Ten artykuł w dokumentacji online objaśnia optymalizację podzapytań znacznie bardziej szczegółowo.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kiedy muszę zakończyć połączenie mysqli (baza danych)?

  2. Jak zwiększyć wartość w MySQL za pomocą PHP mysqli

  3. LOAD DATA INFILE łatwo przekonwertować RRRRMMDD na RRRR-MM-DD?

  4. Czy istnieje sterownik Go Mysql, który obsługuje wiele instrukcji w jednym ciągu?

  5. Czy mysqli_real_escape_string wystarczy, aby uniknąć wstrzyknięcia SQL lub innych ataków SQL?