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

Jak dosáhnu toho, aby MySQL používala INDEX pro zobrazení dotazu?

Jak přimějete MySQL k použití indexu pro dotaz pohledu? Krátká odpověď, poskytněte index, který může MySQL použít.

V tomto případě je optimální index pravděpodobně "krycí" index:

... ON highscores (player, happened_in, score)

Je pravděpodobné, že MySQL použije tento index a EXPLAIN zobrazí:"Using index" kvůli WHERE player = 24 (predikát rovnosti na úvodním sloupci v indexu. GROUP BY happened_id (druhý sloupec v indexu), může umožnit MySQL optimalizovat to pomocí indexu, aby se zabránilo operaci řazení. Včetně score sloupec v indexu umožní uspokojit dotaz zcela z indexu, aniž byste museli navštěvovat (vyhledávat) datové stránky, na které index odkazuje.

To je rychlá odpověď. Delší odpověď je, že je velmi nepravděpodobné, že MySQL použije index s úvodním sloupcem happened_id pro dotaz zobrazení.

Proč zobrazení způsobuje problém s výkonem

Jedním z problémů, které máte s pohledem MySQL, je, že MySQL „netlačí“ predikát z vnějšího dotazu dolů do dotazu pohledu.

Váš vnější dotaz uvádí WHERE happened_in = 2006 . Optimalizátor MySQL nebere v úvahu predikát, když spouští vnitřní "view dotaz". Tento dotaz pro zobrazení se provede samostatně, před vnějším dotazem. Výsledná sada z provedení tohoto dotazu se "materializuje"; to znamená, že výsledky jsou uloženy jako přechodná tabulka MyISAM. (MySQL tomu říká „odvozená tabulka“ a tento název, který používají, dává smysl, když rozumíte operacím, které MysQL provádí.)

Sečteno a podtrženo, index, který jste definovali na happened_in není používán MySQL, když spouští dotaz, který tvoří definici pohledu.

Po vytvoření zprostředkující "odvozené tabulky" se POTOM provede vnější dotaz s použitím této "odvozené tabulky" jako zdroje řádků. Při spuštění tohoto vnějšího dotazu dojde k happened_in = 2006 predikát se hodnotí.

Všimněte si, že jsou uloženy všechny řádky z dotazu zobrazení, což (ve vašem případě) je řádek pro KAŽDOU hodnotu happened_in , nejen ten, pro který zadáte predikát rovnosti ve vnějším dotazu.

Způsob, jakým jsou zpracovávány pohledové dotazy, může být některými „neočekávaný“, a to je jeden z důvodů, proč použití „pohledů“ v MySQL může vést k problémům s výkonem ve srovnání se způsobem, jakým jsou dotazy na pohledy zpracovávány jinými relačními databázemi.

Zlepšení výkonu dotazu zobrazení pomocí vhodného krycího indexu

Vzhledem k vaší definici pohledu a vašemu dotazu by asi nejlepší, co získáte, byla metoda přístupu „Using index“ pro dotaz na pohled. K tomu budete potřebovat krycí index, např.

... ON highscores (player, happened_in, score).

To bude pravděpodobně nejužitečnější index (z hlediska výkonu) pro vaši stávající definici pohledu a váš stávající dotaz. player sloupec je úvodní sloupec, protože v dotazu zobrazení máte v tomto sloupci predikát rovnosti. happened_in sloupec je další, protože na tomto sloupci máte operaci GROUP BY a MySQL bude moci tento index použít k optimalizaci operace GROUP BY. Zahrnujeme také score sloupec, protože to je jediný další sloupec odkazovaný ve vašem dotazu. Díky tomu je index „krycí“ index, protože MySQL dokáže uspokojit tento dotaz přímo z indexových stránek, aniž by bylo nutné navštěvovat jakékoli stránky v podkladové tabulce. A to je tak dobré, jak se dostaneme z plánu dotazů:"Using index" bez "Using filesort".

Porovnejte výkon se samostatným dotazem bez odvozené tabulky

Můžete porovnat plán provádění vašeho dotazu se zobrazením vs. ekvivalentní samostatný dotaz:

SELECT player
     , MAX(score) AS highest_score
     , happened_in
 FROM highscores
WHERE player = 24
  AND happened_in = 2006
GROUP
   BY player
    , happened_in

Samostatný dotaz může také využívat krycí index, např.

... ON highscores (player, happened_in, score)

ale bez potřeby zhmotnit přechodnou tabulku MyISAM.

Nejsem si jistý, zda některý z předchozích poskytuje přímou odpověď na otázku, kterou jste položili.

Otázka:Jak dosáhnu toho, aby MySQL používala INDEX pro zobrazení dotazu?

Odpověď:Definujte vhodný INDEX, který může dotaz zobrazení použít.

Krátká odpověď je poskytnout "krycí index" (index zahrnuje všechny sloupce odkazované v dotazu na zobrazení). Počáteční sloupce v tomto indexu by měly být sloupce, na které odkazují predikáty rovnosti (ve vašem případě sloupec player by byl vedoucí sloupec, protože máte player = 24 predikát v dotazu. Sloupce odkazované v GROUP BY by také měly být vedoucími sloupci v indexu, což umožňuje MySQL optimalizovat GROUP BY pomocí indexu namísto použití operace řazení.

Klíčovým bodem je, že dotaz zobrazení je v podstatě samostatný dotaz; výsledky z tohoto dotazu se uloží do přechodné "odvozené" tabulky (tabulka MyISAM, která se vytvoří, když se spustí dotaz na pohled.

Používání pohledů v MySQL nemusí být nutně „špatný nápad“, ale důrazně bych varoval ty, kteří se rozhodnou používat pohledy v MySQL, aby si VĚDOMI toho, jak MySQL zpracovává dotazy, které na tyto pohledy odkazují. A způsob, jakým MySQL zpracovává pohledové dotazy, se liší (výrazně) od způsobu, jakým jsou pohledové dotazy zpracovávány jinými databázemi (např. Oracle, SQL Server).



  1. Používejte relační databáze MySQL na Fedoře 13

  2. Jak udělat RAND() deterministický v SQL Server

  3. Připojení k databázi MySQL v .NET

  4. Regulární výraz (RegEx) pro IPv6 Oddělený od IPv4