sql >> Databasteknik >  >> RDS >> Sqlserver

Vilka är de huvudsakliga skillnaderna mellan OPTION(OPTIMERA FÖR OKÄNT) och OPTION(OMKOMPILERA)?

Ja, det kommer det.

Det finns två huvudsakliga skillnader mellan OPTION(OPTIMIZE FOR UNKNOWN) och OPTION(RECOMPILE) som framgår av detta citat från MSDN :

Så de två huvudsakliga skillnaderna är:

  1. Cachning (eller inte) av frågeplanen.

Vanligtvis cachelagras den genererade frågeplanen och återanvänds. OPTIMIZE FOR UNKNOWN påverkar inte denna funktion hos motorn. RECOMPILE undertrycker denna funktion och säger åt motorn att kassera planen och inte lägga den i cachen.

  1. Använda (eller inte) faktiska parametervärden under plangenerering.

Vanligtvis "sniffar" optimeraren parametervärdena och använder dessa värden när planen genereras. OPTIMIZE FOR UNKNOWN undertrycker denna funktion och säger åt motorn att behandla alla parametrar som om deras värden var okända. Optimizer har inbyggda regler och heuristik hur man använder tillgänglig statistik för olika filtreringskriterier. Se Optimera för... Medelmåttig? för mer detaljer. Normalt används parametersniffning vid den första körningen av frågan/lagrade proceduren och använder parametrarnas värden under den första körningen. Den genererade planen cachelagras och kan senare återanvändas.

En icke-uppenbar sak att komma ihåg här är att i båda fallen (normalt utan några frågetips och med OPTIMIZE FOR UNKNOWN ledtråd) måste den genererade planen vara giltig och ge korrekt resultat för alla möjligt parametervärde. Den är skräddarsydd för de sniffade värdena som användes under den första körningen i fallet med normal/ingen antydan; den är inte anpassad till något specifikt värde i OPTIMIZE FOR UNKNOWN fall, men det är fortfarande giltigt om parametern ändras senare på något sätt.

Detta är viktigt och det hindrar optimeraren från att utföra vissa transformationer och förenklingar av planen.

OPTION(RECOMPILE) tillåter optimeraren att infoga de faktiska parametrarnas värden under varje körning och optimeraren använder de faktiska parametrarnas värden för att skapa en bättre plan. Det behöver inte oroa dig för att den genererade planen kanske inte fungerar med något annat parametervärde, eftersom planen inte kommer att cachelagras och återanvändas.

Denna effekt är mest synlig för Dynamiska sökvillkor frågor. Till exempel:

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)

Om @ParamSomeID är 0 Optimizer skulle behandla frågan som om den inte hade någon WHERE klausul överhuvudtaget. Planen skulle inte nämna OtherTable alls.

Om @ParamSomeID är -1 , skulle planen gå med i T till OtherTable genom att använda Left Anti Semi Join och skanna hela OtherTable .

Om @ParamSomeID är, säg, 5, skulle planen göra en indexsökning i unikt index på OtherTable och läs endast en rad från OtherTable .

Utan OPTION(RECOMPILE) denna typ av förenkling och omvandling skulle inte ske.

Ytterligare ett skäl att använda OPTION(RECOMPILE) är när din datadistribution är väldigt skev. Till exempel har du en tabell med 1M rader. En kolumn har värde 0 i 990 000 rader och värden från 1 till 10 i 1 000 rader. Frågorna som filtrerar på den här kolumnen bör ha olika planer beroende på filtrets faktiska värde.

I båda exemplen ovan OPTIMIZE FOR UNKNOWN skulle generera en medioker plan.



  1. Ungefär hur snabb är JSON -> JSONB kolumnkonvertering i Postgres 9.4

  2. Använder 'LIKE' med resultatet av en SQL-underfråga

  3. Vad är det för fel på den här mysql-anslutningssträngen?

  4. Ändra alla tabeller i databasen