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

Optimering af mysql-forespørgsel (synes godt om/kan ikke lide)

Med hensyn til ydeevne kan disse korrelerede underforespørgsler spise din frokost. Og spis også din madpakke til store sæt på grund af den måde, MySQL behandler dem på. Hver af disse underforespørgsler udføres for hver række, der returneres i den ydre forespørgsel. Og det kan blive meget dyrt for store sæt.

En alternativ tilgang er at bruge en inline-visning til at materialisere likes og dislikes for alt indhold, og derefter udføre en join-operation til det.

Men denne tilgang kan også være dyr, især når du kun har brug for at stemme "tæller" for blot nogle få indholdsrækker ud af en bazillion rækker. Ofte er der et prædikat fra den ydre forespørgsel, som også kan inkorporeres i inline-visningen, for at begrænse antallet af rækker, der skal undersøges og returneres.

Vi ønsker at bruge en OUTER join til den inline-visning, så den returnerer et resultat svarende til din forespørgsel; returnerer en række fra content når der ikke er nogen matchende rækker i vote tabel.

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 ... ]

Bemærk, at den inline-visningsforespørgsel (aliasset som v ) kommer til at se på HVER enkelt række fra votes bord. Hvis du kun har brug for en delmængde, så overvej at tilføje et passende prædikat (enten i en WHERE-sætning eller som en JOIN til en anden tabel). Der er ingen indikation fra [... OTHER STUFF ...] i din forespørgsel, om det kun returnerer nogle få rækker fra content eller hvis du har brug for alle rækkerne, fordi du bestiller efter likes osv.

For et lille antal rækker valgt fra content tabel, kan det faktisk være hurtigere at bruge de korrelerede underforespørgsler (som i din forespørgsel) end at realisere en enorm indlejret visning og udføre en joinoperation mod den.

Åh... og for begge forespørgsler siger det sig selv, at et passende indeks på votes tabel med en ledende kolonne af cId vil gavne ydeevnen. Til inline-visningen ønsker du ikke, at overhead af MySQL skal udføre en filesort handling på alle disse rækker for at udføre GROUP BY. Og for de korrelerede underforespørgsler vil du have, at de skal bruge en indeksområdescanning, ikke en fuld scanning.



  1. Bedste måde at sammenligne VARCHAR2 med CHAR

  2. Varchar-problem på Mysql 2147483647

  3. mysql-struktur til kommentarer og kommentarsvar

  4. Hvordan man laver en rullende sum, skal hver række inkludere summen af ​​tidligere rækker