sql >> Database teknologi >  >> RDS >> Mysql

kan det udføres hurtigere med store mængder data [MySQL]

Ser på din EXPLAIN output, var jeg bekymret for, at din brug af underforespørgsler havde resulteret i en suboptimal brug af indekser. Jeg følte (uden nogen begrundelse - og her kan jeg meget vel tage fejl) denne omskrivning ved hjælp af JOIN kan føre til en mere optimeret forespørgsel.

For at gøre det skal vi forstå, hvad det er, din forespørgsel er beregnet til. Det ville have hjulpet, hvis dit spørgsmål havde formuleret det, men efter lidt hovedskraber besluttede jeg, at din forespørgsel forsøgte at hente en liste over alle andre søgeord, der vises i en artikel, der indeholder et givet søgeord, sammen med et antal af alle artikler, hvor disse søgeord forekommer .

Lad os nu genopbygge forespørgslen i etaper:

  1. Hent "enhver artikel, der indeholder et givet søgeord " (ikke bekymre dig om dubletter):

    SELECT ca2.article_id
    FROM
           career_article_keyword AS ca2
    WHERE
          ca2.keyword_id = 9;
    
  2. Hent "alle andre søgeord, der vises i [ovenstående] "

    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. Hent "[ovenstående], sammen med en optælling af alle artikler, hvori disse søgeord forekommer "

    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. Til sidst vil vi tilføje selve det matchende søgeord til outputtet fra career_keyword tabel:

    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;
    

En ting, der umiddelbart står klart, er, at din oprindelige forespørgsel refererede til career_keywords to gange, hvorimod denne omskrevne forespørgsel kun refererer til denne tabel én gang; dette alene kan forklare ydeevneforskellen - prøv at fjerne den anden reference til den (dvs. hvor den vises i din første underforespørgsel), da den er helt overflødig der.

Når vi ser tilbage på denne forespørgsel, kan vi se, at joinforbindelser udføres i følgende kolonner:

  • career_keywords.keyword_id i ck JOIN ca0

    Denne tabel definerer PRIMARY KEY (`keyword_id`) , så der er et godt indeks, som kan bruges til denne join.

  • career_article_keyword.article_id i ca1 JOIN ca2

    Denne tabel definerer UNIQUE KEY `article_id` (`article_id`,`keyword_id`) og siden article_id er kolonnen længst til venstre i dette indeks, er der et godt indeks, som kan bruges til denne join.

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

    Der er intet indeks, der kan bruges til denne joinforbindelse:det eneste indeks, der er defineret i denne tabel, har en anden kolonne, article_id til venstre for keyword_id - så MySQL kan ikke finde keyword_id poster i indekset uden først at kende article_id . Jeg foreslår, at du opretter et nyt indeks, som har keyword_id som kolonnen længst til venstre.

    (Behovet for dette indeks kunne ligeledes have været konstateret direkte ved at se på din oprindelige forespørgsel, hvor dine to yderste forespørgsler udfører joinforbindelser på den kolonne.)




  1. MySQL - indsæt data fra en anden tabel fusioneret med konstanter

  2. PHP multiple billedfil upload og lagring til mappe og database

  3. Hvad er den bedste måde at ekko resultater fra databasen til html-kode i PHP?

  4. Konverter fra mysqli_query til mysqli forberedt sætning ved hjælp af mysql PASSWORD funktion