sql >> Databáze >  >> RDS >> Sqlserver

Jaké jsou hlavní rozdíly mezi OPTION (OPTIMIZE FOR UNKNOWN) a OPTION (RECOMPILE)?

Ano, bude.

Mezi OPTION(OPTIMIZE FOR UNKNOWN) jsou dva hlavní rozdíly a OPTION(RECOMPILE) jak je vidět z tohoto citátu z MSDN :

Takže dva hlavní rozdíly jsou:

  1. Ukládání (nebo neukládání) plánu dotazů do mezipaměti.

Obvykle je vygenerovaný plán dotazů uložen do mezipaměti a znovu použit. OPTIMIZE FOR UNKNOWN neovlivňuje tuto vlastnost motoru. RECOMPILE potlačí tuto funkci a řekne enginu, aby zahodil plán a nevkládal ho do mezipaměti.

  1. Použití (nebo ne) skutečných hodnot parametrů během generování plánu.

Optimalizátor obvykle „načuchá“ hodnoty parametrů a použije je při generování plánu. OPTIMIZE FOR UNKNOWN potlačí tuto funkci a řekne motoru, aby zacházel se všemi parametry, jako by jejich hodnoty byly neznámé. Optimalizátor má vestavěná pravidla a heuristiku, jak používat dostupné statistiky pro různá kritéria filtrování. Viz Optimalizace pro… Průměrná? Více podrobností. Normálně se sniffing parametrů používá při prvním spuštění dotazu/uložené procedury a používá hodnoty parametrů během prvního spuštění. Vygenerovaný plán je uložen do mezipaměti a později jej lze znovu použít.

Jedna nezřejmá věc, kterou je třeba si pamatovat, je, že v obou případech (normální bez jakýchkoliv dotazů a s OPTIMIZE FOR UNKNOWN hint) vygenerovaný plán musí být platný a musí poskytovat správný výsledek pro jakýkoli možná hodnota parametru. Je přizpůsoben načteným hodnotám, které byly použity při prvním spuštění v případě normálního/bez náznaku; není přizpůsoben žádné konkrétní hodnotě v OPTIMIZE FOR UNKNOWN případ, ale je stále platný, pokud se parametr později jakýmkoli způsobem změní.

To je významné a zabraňuje to optimalizátoru provádět určité transformace a zjednodušení plánu.

OPTION(RECOMPILE) umožňuje optimalizátoru vkládat skutečné hodnoty parametrů během každého běhu a optimalizátor používá skutečné hodnoty parametrů k vytvoření lepšího plánu. Nemusí se bát, že vygenerovaný plán nemusí fungovat s nějakou jinou hodnotou parametru, protože plán nebude uložen do mezipaměti a znovu použit.

Tento efekt je většinou viditelný pro podmínky dynamického vyhledávání dotazy. Například:

SELECT ...
FROM T
WHERE
    (@ParamSomeID = 0)
    OR
    (
        @ParamSomeID = -1
        AND
        T.SomeID NOT IN
        (
            SELECT OtherTable.SomeID
            FROM OtherTable
        )
    )
    OR
    (
        T.SomeID IN
        (
            SELECT OtherTable.SomeID
            FROM OtherTable
            WHERE OtherTable.SomeID = @ParamSomeID
        )
    )
OPTION(RECOMPILE)

Pokud @ParamSomeID je 0 Optimalizátor by zacházel s dotazem, jako by neměl žádné WHERE klauzule vůbec. Plán by nezmiňoval OtherTable vůbec.

Pokud @ParamSomeID je -1 , plán by se připojil k T do OtherTable pomocí Left Anti Semi Join a naskenuje celou OtherTable .

Pokud @ParamSomeID je, řekněme, 5, plán by provedl hledání indexu v jedinečném indexu na OtherTable a číst pouze jeden řádek z OtherTable .

Bez OPTION(RECOMPILE) k takovému zjednodušení a transformaci by nedošlo.

Další důvod, proč použít OPTION(RECOMPILE) když je distribuce dat velmi zkreslená. Máte například tabulku s 1 milionem řádků. Jeden sloupec má hodnotu 0 v 990 000 řádcích a hodnoty od 1 do 10 v 1 000 řádcích. Dotazy, které filtrují v tomto sloupci, by měly mít různé plány v závislosti na skutečné hodnotě filtru.

V obou výše uvedených příkladech OPTIMIZE FOR UNKNOWN by vytvořil průměrný plán.



  1. Je možné spustit dvě instance kontejnerů docker na jednom kontejneru databáze mysql?

  2. Přehled vygenerovaných sloupců pro PostgreSQL

  3. Průvodce návrhem databáze pro RBAC v MySQL

  4. Existuje nějaký způsob, jak zajistit, aby PostgreSQL nesbalil interpunkci a mezery při řazení pomocí jazyka?