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

czy może być wykonany szybciej z dużą ilością danych [MySQL]

Patrząc na swoje EXPLAIN dane wyjściowe, obawiałem się, że twoje użycie podzapytań spowodowało nieoptymalne użycie indeksów. czułem (bez żadnego uzasadnienia - i co do tego mogę się mylić), że przepisywanie za pomocą JOIN może prowadzić do bardziej zoptymalizowanego zapytania.

Aby to zrobić, musimy zrozumieć, do czego ma służyć Twoje zapytanie. Pomogłoby, gdyby Twoje pytanie zostało wyartykułowane, ale po krótkim zastanowieniu stwierdziłem, że Twoje zapytanie próbuje pobrać listę wszystkich innych słów kluczowych, które pojawiają się w każdym artykule zawierającym dane słowo kluczowe, wraz z liczbą wszystkich artykułów, w których pojawiają się te słowa kluczowe .

Teraz przebudujmy zapytanie etapami:

  1. Pobierz „dowolny artykuł zawierający określone słowo kluczowe " (nie martw się o duplikaty):

    SELECT ca2.article_id
    FROM
           career_article_keyword AS ca2
    WHERE
          ca2.keyword_id = 9;
    
  2. Pobierz „wszystkie inne słowa kluczowe, które pojawiają się w [powyżej] "

    SELECT ca1.keyword_id
    FROM
           career_article_keyword AS ca1
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ca1.keyword_id;
    
  3. Pobierz „[powyższe] wraz z liczbą wszystkich artykułów, w których pojawiają się te słowa kluczowe "

    SELECT ca1.keyword_id, COUNT(DISTINCT ca0.article_id) AS cnt
    FROM
           career_article_keyword AS ca0
      JOIN career_article_keyword AS ca1 USING (keyword_id)
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ca1.keyword_id
    ORDER BY cnt DESC;
    
  4. Na koniec chcemy dodać do wyniku pasujące słowo kluczowe z career_keyword tabela:

    SELECT ck.keyword_id, ck.keyword, COUNT(DISTINCT ca0.article_id) AS cnt
    FROM
           career_keywords        AS ck 
      JOIN career_article_keyword AS ca0 USING (keyword_id)
      JOIN career_article_keyword AS ca1 USING (keyword_id)
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ck.keyword_id -- equal to ca1.keyword_id due to join conditions
    ORDER BY cnt DESC;
    

Jedno, co jest od razu jasne, to to, że oryginalne zapytanie odnosiło się do career_keywords dwukrotnie, podczas gdy to przepisane zapytanie odwołuje się do tej tabeli tylko raz; samo to może wyjaśniać różnicę w wydajności — spróbuj usunąć drugie odniesienie do niego (tj. miejsce, w którym pojawia się w pierwszym podzapytaniu), ponieważ jest tam całkowicie zbędne.

Patrząc wstecz na to zapytanie, widzimy, że połączenia są wykonywane w następujących kolumnach:

  • career_keywords.keyword_id w ck JOIN ca0

    Ta tabela definiuje PRIMARY KEY (`keyword_id`) , więc istnieje dobry indeks, którego można użyć do tego połączenia.

  • career_article_keyword.article_id w ca1 JOIN ca2

    Ta tabela definiuje UNIQUE KEY `article_id` (`article_id`,`keyword_id`) i ponieważ article_id jest skrajną lewą kolumną w tym indeksie, istnieje dobry indeks, którego można użyć do tego połączenia.

  • career_article_keyword.keyword_id w ck JOIN ca0 i ca0 JOIN ca1

    Nie ma indeksu, którego można użyć dla tego złączenia:jedyny indeks zdefiniowany w tej tabeli ma inną kolumnę, article_id na lewo od keyword_id - więc MySQL nie może znaleźć keyword_id wpisy w indeksie bez uprzedniej znajomości article_id . Proponuję utworzyć nowy indeks, który ma keyword_id w skrajnej lewej kolumnie.

    (Zapotrzebowanie na ten indeks można było również ustalić bezpośrednio na podstawie oryginalnego zapytania, w którym dwa najbardziej zewnętrzne zapytania dokonują złączeń w tej kolumnie).




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wykrywanie zablokowanych tabel (zablokowanych przez LOCK TABLE)

  2. Jak stworzyć bazę danych za pomocą Liquibase

  3. Joomla! 3 instalacja zawiesza się podczas tworzenia tabeli bazy danych

  4. Funkcja strtotime() PHP jest nieprawidłowa o 1 godzinę?

  5. Przed czym MySQL próbuje zapobiec zjawisku, blokując całą tabelę po wykonaniu instrukcji Delete z warunkiem na nieindeksowanej kolumnie