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

Optymalizacja zapytania mysql (lubi/nie lubi)

Jeśli chodzi o wydajność, te skorelowane podzapytania mogą zjeść obiad. Pochłoń też swoje pudełko śniadaniowe, w przypadku dużych zestawów, ze względu na sposób, w jaki MySQL je przetwarza. Każde z tych podzapytań jest wykonywane dla każdego wiersza zwróconego w zapytaniu zewnętrznym. A to może być bardzo drogie w przypadku dużych zestawów.

Alternatywnym podejściem jest użycie widoku wbudowanego w celu zmaterializowania upodobań i niechęci do wszystkich treści, a następnie wykonanie operacji łączenia.

Ale to podejście może być również kosztowne, szczególnie gdy potrzebujesz tylko „liczy się” głosów dla zaledwie kilku wierszy treści, z miliarda wierszy. Często istnieje predykat z zapytania zewnętrznego, który można również włączyć do widoku wbudowanego, aby ograniczyć liczbę wierszy, które należy zbadać i zwrócić.

Chcemy użyć sprzężenia OUTER do tego wbudowanego widoku, więc zwraca on wynik odpowiadający zapytaniu; zwracanie wiersza z content gdy nie ma pasujących wierszy w vote tabela.

SELECT [... BUNCH OF FIELDS ...]
     , COALESCE(v.likes,0) AS likes
     , COALESCE(v.dislikes,0) AS dislikes
     , COALESCE(v.myvote,'.Constants::NO_VOTE.') AS myvote
  FROM content c
  LEFT
  JOIN ( SELECT vt.cId
              , SUM(vt.vote = '.Constants::LIKE.') AS likes
              , SUM(vt.vote = '.Constants::DISLIKE.') AS dislikes
              , MAX(IF(vt.userId = '.USER_ID.',vt.vote,NULL)) AS myvote
           FROM votes vt
          GROUP
             BY vt.cId
       ) v
    ON v.cId = c.contentId

       [... OTHER STUFF ... ]

Zwróć uwagę, że zapytanie wbudowanego widoku (z aliasem v ) przyjrzy się KAŻDEMU wierszowi z votes stół. Jeśli potrzebujesz tylko podzbioru, rozważ dodanie odpowiedniego predykatu (w klauzuli WHERE lub jako JOIN do innej tabeli). Brak wskazania z [... OTHER STUFF ...] w zapytaniu, czy zwraca tylko kilka wierszy z content lub jeśli potrzebujesz wszystkich wierszy, ponieważ zamawiasz według likes itp.

Dla małej liczby wierszy wybranych z content tabeli, użycie skorelowanych podzapytań (jak w zapytaniu) może być w rzeczywistości szybsze niż zmaterializowanie ogromnego widoku wbudowanego i wykonanie wobec niego operacji łączenia.

Aha... i dla obu zapytań, jest rzeczą oczywistą, że odpowiedni indeks na votes tabela z wiodącą kolumną cId poprawi wydajność. W przypadku widoku wbudowanego nie chcesz, aby obciążenie MySQL wymagało wykonywania filesort na wszystkich tych wierszach wykonać operację GROUP BY. A dla skorelowanych podzapytań chcesz, aby używały skanowania zakresu indeksów, a nie pełnego skanowania.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL:WYMAGAJ SSL nie pokazane w grantach

  2. Identyfikator z listy, którego nie ma w tabeli

  3. Jak sformatować numer za pomocą . jako separator tysięcy i jako separator dziesiętny?

  4. Jak mogę zoptymalizować to zapytanie, wykonanie zajmuje więcej niż minutę

  5. Przechowuj wrażliwe dane w Silverstripe 3.1