sql >> Databasteknik >  >> RDS >> Mysql

Optimera mysql-fråga (gillar/ogillar)

När det gäller prestanda kan de korrelerade underfrågorna äta din lunch. Och sluka din lunchlåda också, för stora set, på grund av hur MySQL bearbetar dem. Var och en av dessa underfrågor exekveras för varje rad som returneras i den yttre frågan. Och det kan bli väldigt dyrt för stora uppsättningar.

Ett alternativt tillvägagångssätt är att använda en inline-vy för att förverkliga vad som gillas och ogillas för allt innehåll och sedan göra en kopplingsoperation till det.

Men det här tillvägagångssättet kan också vara dyrt, särskilt när du bara behöver rösten "räknas" för bara några innehållsrader, av en basillion rader. Ofta finns det ett predikat från den yttre frågan som också kan införlivas i inlinevyn, för att begränsa antalet rader som behöver undersökas och returneras.

Vi vill använda en OUTER-koppling till den inline-vyn, så den returnerar ett resultat som motsvarar din fråga; returnera en rad från content när det inte finns några matchande rader i vote bord.

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

Observera att inline-vyfrågan (alias som v ) kommer att titta på VARJE enskild rad från votes tabell. Om du bara behöver en delmängd, överväg att lägga till ett lämpligt predikat (antingen i en WHERE-sats eller som en JOIN till en annan tabell). Det finns ingen indikation från [... OTHER STUFF ...] i din fråga om det bara returnerar några rader från content eller om du behöver alla rader för att du beställer efter likes osv.

För ett litet antal rader valda från content tabell, att använda de korrelerade underfrågorna (som i din fråga) kan faktiskt vara snabbare än att materialisera en enorm inlinevy och utföra en kopplingsoperation mot den.

Åh... och för båda frågorna är det självklart att ett lämpligt index på votes tabell med en ledande kolumn cId kommer att gynna prestanda. För inlinevyn vill du inte att overheaden för MySQL måste utföra en filesort operation på alla dessa rader för att göra GROUP BY. Och för de korrelerade underfrågorna vill du att de ska använda en skanning av indexintervall, inte en fullständig genomsökning.



  1. 11 SQL Server-index bästa praxis för förbättrad prestandajustering

  2. Odefinierad funktion mysql_connect()

  3. mysql_connect VS mysql_pconnect

  4. Lägga till i ett databasfält istället för att skriva över det (MySQL UPDATE-funktion)