sql >> Database >  >> RDS >> Sqlserver

Wat zijn de belangrijkste verschillen tussen OPTIE (OPTIMALISEREN VOOR ONBEKEND) en OPTIE (HERCOMPIEREN)?

Ja, dat zal wel.

Er zijn twee belangrijke verschillen tussen OPTION(OPTIMIZE FOR UNKNOWN) en OPTION(RECOMPILE) zoals blijkt uit dit citaat van MSDN :

De twee belangrijkste verschillen zijn dus:

  1. Caching (of niet) van het queryplan.

Gewoonlijk wordt het gegenereerde queryplan in de cache opgeslagen en opnieuw gebruikt. OPTIMIZE FOR UNKNOWN heeft geen invloed op deze eigenschap van de motor. RECOMPILE onderdrukt deze functie en vertelt de engine om het plan te negeren en niet in de cache te plaatsen.

  1. Gebruik (of niet) werkelijke parameterwaarden tijdens het genereren van een plan.

Gewoonlijk "snuffelt" de optimizer de parameterwaarden en gebruikt deze waarden bij het genereren van het plan. OPTIMIZE FOR UNKNOWN onderdrukt deze functie en vertelt de engine om alle parameters te behandelen alsof hun waarden onbekend waren. Optimizer heeft ingebouwde regels en heuristieken voor het gebruik van beschikbare statistieken voor verschillende filtercriteria. Zie Optimaliseren voor... Middelmatig? voor meer details. Normaal gesproken wordt het snuiven van parameters gebruikt bij de eerste uitvoering van de query/opgeslagen procedure en worden de waarden van parameters gebruikt tijdens de eerste uitvoering. Het gegenereerde plan wordt in de cache opgeslagen en kan later opnieuw worden gebruikt.

Een niet voor de hand liggend ding om te onthouden is dat in beide gevallen (normaal zonder enige vraaghints en met OPTIMIZE FOR UNKNOWN hint) het gegenereerde plan moet geldig zijn en het juiste resultaat opleveren voor elke mogelijke parameterwaarde. Het is afgestemd op de gesnoven waarden die werden gebruikt tijdens de eerste run in het geval van normaal/geen hint; het is niet afgestemd op een specifieke waarde in de OPTIMIZE FOR UNKNOWN geval, maar het is nog steeds geldig als de parameter later op enigerlei wijze verandert.

Dit is significant en het verhindert dat de optimizer bepaalde transformaties en vereenvoudigingen van het plan uitvoert.

OPTION(RECOMPILE) stelt de optimizer in staat om de werkelijke waarden van parameters tijdens elke run inline te plaatsen en de optimizer gebruikt de werkelijke waarden van parameters om een ​​beter plan te genereren. U hoeft zich geen zorgen te maken dat het gegenereerde plan mogelijk niet werkt met een andere parameterwaarde, omdat het plan niet in de cache wordt opgeslagen en opnieuw wordt gebruikt.

Dit effect is vooral zichtbaar voor de Dynamische zoekvoorwaarden vragen. Bijvoorbeeld:

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)

Als @ParamSomeID is 0 optimizer zou de zoekopdracht behandelen alsof deze geen WHERE . heeft clausule helemaal niet. Het plan zou OtherTable niet vermelden helemaal niet.

Als @ParamSomeID is -1 , zou het plan aansluiten bij T naar OtherTable met Left Anti Semi Join en scande de hele OtherTable .

Als @ParamSomeID is, laten we zeggen, 5, het plan zou een index zoeken in een unieke index op OtherTable en lees slechts één rij uit OtherTable .

Zonder OPTION(RECOMPILE) dit soort vereenvoudiging en transformatie zou niet plaatsvinden.

Nog een reden om OPTION(RECOMPILE) te gebruiken is wanneer uw gegevensverdeling erg scheef is. U hebt bijvoorbeeld een tabel met 1 miljoen rijen. Eén kolom heeft de waarde 0 in 990K rijen en waarden van 1 tot 10 in 1K rijen. De zoekopdrachten die op deze kolom filteren, moeten verschillende plannen hebben, afhankelijk van de werkelijke waarde van het filter.

In beide bovenstaande voorbeelden OPTIMIZE FOR UNKNOWN zou een middelmatig plan opleveren.



  1. Alle niet-geclusterde indexen uitschakelen

  2. pyspark gebruiken om verbinding te maken met PostgreSQL

  3. JSON invoegen in MySQL met Python

  4. SQL-query om ontbrekende rijen tussen twee gerelateerde tabellen te vinden