sql >> Database teknologi >  >> RDS >> Sqlserver

Hvad er de vigtigste forskelle mellem OPTION (OPTIMER TIL UKENDT) og OPTION (GENKOMPILER)?

Ja, det vil det.

Der er to hovedforskelle mellem OPTION(OPTIMIZE FOR UNKNOWN) og OPTION(RECOMPILE) som det kan ses af dette citat fra MSDN :

Så de to vigtigste forskelle er:

  1. Caching (eller ej) af forespørgselsplanen.

Normalt cachelagres den genererede forespørgselsplan og genbruges. OPTIMIZE FOR UNKNOWN påvirker ikke denne funktion af motoren. RECOMPILE undertrykker denne funktion og beder motoren om at kassere planen og ikke lægge den i cachen.

  1. Brug (eller ej) faktiske parameterværdier under plangenerering.

Normalt "snuser" optimizer parameterværdierne og bruger disse værdier, når planen genereres. OPTIMIZE FOR UNKNOWN undertrykker denne funktion og fortæller motoren at behandle alle parametre, som om deres værdier var ukendte. Optimizer har indbyggede regler og heuristik, hvordan man bruger tilgængelig statistik til forskellige filtreringskriterier. Se Optimer til... Middelmådig? for flere detaljer. Normalt bruges parametersniffing ved den første kørsel af forespørgslen/den lagrede procedure og bruger værdierne af parametrene under den første kørsel. Den genererede plan cachelagres og kan senere genbruges.

En ikke-oplagt ting at huske her er, at i begge tilfælde (normalt uden nogen forespørgselstip og med OPTIMIZE FOR UNKNOWN tip) skal den genererede plan være gyldig og give korrekte resultater for enhver mulig parameterværdi. Den er skræddersyet til de sniffede værdier, der blev brugt under den første kørsel i normal/no-hint tilfældet; den er ikke skræddersyet til nogen specifik værdi i OPTIMIZE FOR UNKNOWN tilfælde, men det er stadig gyldigt, hvis parameter ændres senere på nogen måde.

Dette er vigtigt, og det forhindrer optimizer i at udføre visse transformationer og forenklinger af planen.

OPTION(RECOMPILE) giver optimizer mulighed for at inline de faktiske værdier af parametre under hver kørsel, og optimizer bruger faktiske værdier af parametre til at generere en bedre plan. Det behøver ikke at bekymre dig om, at den genererede plan muligvis ikke fungerer med en anden parameterværdi, fordi planen ikke bliver cachelagret og genbrugt.

Denne effekt er for det meste synlig for dynamiske søgebetingelser forespørgsler. For eksempel:

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)

Hvis @ParamSomeID er 0 optimizer ville behandle forespørgslen, som om den ikke havde nogen WHERE klausul overhovedet. Planen ville ikke nævne OtherTable overhovedet.

Hvis @ParamSomeID er -1 , ville planen slutte sig til T til OtherTable ved at bruge Left Anti Semi Join og ville scanne hele OtherTable .

Hvis @ParamSomeID er f.eks. 5, ville planen lave en indekssøgning i unikt indeks på OtherTable og læs kun én række fra OtherTable .

Uden OPTION(RECOMPILE) denne form for forenkling og transformation ville ikke ske.

Endnu en grund til at bruge OPTION(RECOMPILE) er, når din datafordeling er meget skæv. For eksempel har du en tabel med 1M rækker. En kolonne har værdi 0 i 990.000 rækker og værdier fra 1 til 10 i 1.000 rækker. De forespørgsler, der filtrerer på denne kolonne, bør have forskellige planer afhængigt af den faktiske værdi af filteret.

I begge eksempler ovenfor OPTIMIZE FOR UNKNOWN ville generere en middelmådig plan.



  1. Hvordan man repræsenterer relationel division (grundlæggende algebra udtryk) i form af SQL

  2. Byg et nyhedsbrevssystem med PHP og MySQL

  3. Brug af sp_ som præfiks for brugerlagrede procedurer i SQL-server, hvilket forårsager ydeevnepåvirkning

  4. hvor rownum=1 forespørgsel tager tid i Oracle