sql >> Databáze >  >> RDS >> Mysql

Optimalizace dotazu mysql (to se mi líbí/nelíbí)

Pokud jde o výkon, tyto korelované poddotazy vám mohou sníst oběd. A zhltněte také svůj obědový box, u velkých sad, kvůli způsobu, jakým je MySQL zpracovává. Každý z těchto poddotazů se provede pro každý řádek vrácený ve vnějším dotazu. A to může být u velkých souborů velmi drahé.

Alternativním přístupem je použít inline zobrazení k zhmotnění toho, co se líbí a nelíbí u veškerého obsahu, a poté k tomu provést operaci spojení.

Tento přístup však může být také drahý, zvláště když potřebujete „počet hlasů“ pouze pro několik řádků obsahu z tisíce řádků. Často existuje predikát z vnějšího dotazu, který lze také začlenit do vloženého pohledu, aby se omezil počet řádků, které je třeba prozkoumat a vrátit.

Chceme použít OUTER spojení s tímto vloženým pohledem, takže vrátí výsledek ekvivalentní vašemu dotazu; vrací řádek z content když v vote nejsou žádné odpovídající řádky tabulka.

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

Všimněte si, že dotaz vloženého zobrazení (s aliasem v ) se podívá na KAŽDÝ řádek z votes stůl. Pokud potřebujete pouze podmnožinu, zvažte přidání vhodného predikátu (buď v klauzuli WHERE nebo jako JOIN do jiné tabulky). Z [... OTHER STUFF ...] nic nenaznačuje ve vašem dotazu, zda vrací jen několik řádků z content nebo pokud potřebujete všechny řádky, protože objednáváte podle likes , atd.

Pro malý počet řádků vybraných z content tabulky, použití korelovaných poddotazů (jako ve vašem dotazu) může být ve skutečnosti rychlejší než zhmotnění velkého inline pohledu a provedení operace spojení proti němu.

Ach... a pro oba dotazy je samozřejmé, že příslušný index na votes tabulka s úvodním sloupcem cId prospěje výkonu. U inline zobrazení nechcete, aby režie MySQL musela provádět filesort operace na všech těchto řádcích pro provedení GROUP BY. A pro korelované poddotazy chcete, aby používaly skenování rozsahu indexu, nikoli úplné skenování.



  1. Jak formátovat záporné hodnoty pomocí závorek na serveru SQL Server (T-SQL)

  2. SQL Query:Jak získat položky z jednoho sloupce spárovaného s druhým, ale ne naopak

  3. Jak vytvořit tabulku v MySQL při použití Java

  4. Jak předat seznam z Java do Oracle Procedure?