sql >> Database >  >> RDS >> Mysql

kan het sneller worden uitgevoerd met een grote hoeveelheid gegevens [MySQL]

Kijken naar je EXPLAIN output, was ik bang dat uw gebruik van subquery's had geresulteerd in een suboptimaal gebruik van indexen. Ik voelde (zonder enige rechtvaardiging - en hierin kan ik me vergissen) dat herschrijven met JOIN kan leiden tot een meer geoptimaliseerde zoekopdracht.

Om dat te doen, moeten we begrijpen waarvoor uw zoekopdracht is bedoeld. Het zou hebben geholpen als je vraag het had verwoord, maar na een beetje hoofdbrekens besloot ik dat je zoekopdracht probeerde om een lijst op te halen van alle andere trefwoorden die voorkomen in een artikel dat een bepaald trefwoord bevat, samen met een telling van alle artikelen waarin die zoekwoorden voorkomen .

Laten we de query nu in fasen opnieuw opbouwen:

  1. Haal "elk artikel op dat een bepaald zoekwoord bevat " (geen zorgen over duplicaten):

    SELECT ca2.article_id
    FROM
           career_article_keyword AS ca2
    WHERE
          ca2.keyword_id = 9;
    
  2. Haal "alle andere zoekwoorden op die in [het bovenstaande] voorkomen "

    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. Haal "[het bovenstaande] op, samen met een telling van alle artikelen waarin die zoekwoorden voorkomen "

    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. Ten slotte willen we aan de uitvoer het overeenkomende trefwoord zelf toevoegen uit het career_keyword tafel:

    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;
    

Een ding dat meteen duidelijk is, is dat uw oorspronkelijke zoekopdracht verwijst naar career_keywords twee keer, terwijl deze herschreven query slechts één keer naar die tabel verwijst; dit alleen al zou het prestatieverschil kunnen verklaren - probeer de tweede verwijzing ernaar te verwijderen (d.w.z. waar het voorkomt in uw eerste subquery), aangezien het daar volledig overbodig is.

Als we terugkijken op deze zoekopdracht, kunnen we zien dat er samenvoegingen worden uitgevoerd op de volgende kolommen:

  • career_keywords.keyword_id in ck JOIN ca0

    Deze tabel definieert PRIMARY KEY (`keyword_id`) , dus er is een goede index die voor deze join kan worden gebruikt.

  • career_article_keyword.article_id in ca1 JOIN ca2

    Deze tabel definieert UNIQUE KEY `article_id` (`article_id`,`keyword_id`) en, sinds article_id is de meest linkse kolom in deze index, er is een goede index die voor deze join kan worden gebruikt.

  • career_article_keyword.keyword_id in ck JOIN ca0 en ca0 JOIN ca1

    Er is geen index die voor deze join kan worden gebruikt:de enige index die in deze tabel is gedefinieerd, heeft een andere kolom, article_id links van keyword_id - dus MySQL kan keyword_id niet vinden vermeldingen in de index zonder eerst de article_id . te kennen . Ik raad u aan een nieuwe index te maken met keyword_id als de meest linkse kolom.

    (De behoefte aan deze index kan ook direct worden vastgesteld door naar uw oorspronkelijke zoekopdracht te kijken, waar uw twee buitenste zoekopdrachten samenvoegingen uitvoeren op die kolom.)




  1. Oracle-reeks maken die begint met alfanumeriek

  2. Hoe werk ik een waarde in een rij bij in MySQL met behulp van Connector/C++

  3. Hoe te sorteren op vorige datum in de database?

  4. UPDATE .. LIMIT 1 met SqlAlchemy en PostgreSQL