Ik zal niet proberen de volledige details van het snuiven van parameters uit te leggen, maar kortom, nee, dat is niet altijd helpen (en het kan hinderen).
Stel je een tabel (T) voor met een primaire sleutel en een geïndexeerde kolom Datum (A), in de tabel zijn er 1.000 rijen, 400 hebben dezelfde waarde van A (laten we zeggen vandaag 20130122), de resterende 600 rijen zijn de komende 600 dagen , dus slechts 1 record per datum.
Deze vraag:
SELECT *
FROM T
WHERE A = '20130122';
Zal een ander uitvoeringsplan opleveren voor:
SELECT *
FROM T
WHERE A = '20130123';
Aangezien de statistieken aangeven dat voor de eerste 400 van de 1.000 rijen worden geretourneerd, moet de optimizer erkennen dat een tabelscan efficiënter zal zijn dan een bladwijzerzoekopdracht, terwijl de tweede slechts 1 rij oplevert, dus een bladwijzerzoekopdracht zal veel efficiënter.
Nu, terug naar uw vraag, als we hier een procedure van hebben gemaakt:
CREATE PROCEDURE dbo.GetFromT @Param DATE
AS
SELECT *
FROM T
WHERE A = @Param
Ren dan
EXECUTE dbo.GetFromT '20130122'; --400 rows
Het queryplan met de tabelscan zal worden gebruikt, als u de eerste keer dat u het uitvoert '20130123' als parameter gebruikt, wordt het bladwijzeropzoekplan opgeslagen. Zolang de procedure niet opnieuw wordt gecompileerd, blijft het plan hetzelfde. Zoiets doen:
CREATE PROCEDURE dbo.GetFromT @Param VARCHAR(5)
AS
DECLARE @Param2 VARCHAR(5) = @Param;
SELECT *
FROM T
WHERE A = @Param2
Dan wordt dit uitgevoerd:
EXECUTE dbo.GetFromT '20130122';
Hoewel de procedure in één keer wordt gecompileerd, verloopt deze niet goed, dus het queryplan dat bij de eerste compilatie is gemaakt, heeft geen idee dat @Param2 hetzelfde wordt als @param, dus de optimiser (zonder kennis van hoeveel rijen verwachten) gaat ervan uit dat 300 wordt geretourneerd (30%), daarom wordt een tabelscan efficiënter geacht dan het opzoeken van een bladwijzer. Als u dezelfde procedure zou uitvoeren met '20130123' als parameter, zou dit hetzelfde plan opleveren (ongeacht met welke parameter het voor het eerst werd aangeroepen) omdat de statistieken niet kunnen worden gebruikt voor een onbekende waarde. Dus het uitvoeren van deze procedure voor '20130122' zou efficiënter zijn, maar voor alle andere waarden zou het minder efficiënt zijn dan zonder lokale parameters (ervan uitgaande dat de procedure zonder lokale parameters eerst werd aangeroepen met alles behalve '20130122')
Enkele vragen om aan te tonen, zodat u de uitvoeringsplannen zelf kunt bekijken
Schema en voorbeeldgegevens maken
CREATE TABLE T (ID INT IDENTITY(1, 1) PRIMARY KEY, A DATE NOT NULL, B INT,C INT, D INT, E INT);
CREATE NONCLUSTERED INDEX IX_T ON T (A);
INSERT T (A, B, C, D, E)
SELECT TOP 400 CAST('20130122' AS DATE), number, 2, 3, 4
FROM Master..spt_values
WHERE type = 'P'
UNION ALL
SELECT TOP 600 DATEADD(DAY, number, CAST('20130122' AS DATE)), number, 2, 3, 4
FROM Master..spt_values
WHERE Type = 'P';
GO
CREATE PROCEDURE dbo.GetFromT @Param DATE
AS
SELECT *
FROM T
WHERE A = @Param
GO
CREATE PROCEDURE dbo.GetFromT2 @Param DATE
AS
DECLARE @Param2 DATE = @Param;
SELECT *
FROM T
WHERE A = @Param2
GO
Procedures uitvoeren (met het daadwerkelijke uitvoeringsplan):
EXECUTE GetFromT '20130122';
EXECUTE GetFromT '20130123';
EXECUTE GetFromT2 '20130122';
EXECUTE GetFromT2 '20130123';
GO
EXECUTE SP_RECOMPILE GetFromT;
EXECUTE SP_RECOMPILE GetFromT2;
GO
EXECUTE GetFromT '20130123';
EXECUTE GetFromT '20130122';
EXECUTE GetFromT2 '20130123';
EXECUTE GetFromT2 '20130122';
Je zult zien dat de eerste keer GetFromT
is gecompileerd, gebruikt een tabelscan en behoudt deze wanneer uitgevoerd met de parameter '20130122', GetFromT2
maakt ook gebruik van een tabelscan en behoudt het plan voor '20130122'.
Nadat de procedures voor hercompilatie zijn ingesteld en opnieuw worden uitgevoerd (let op in een andere volgorde), GetFromT
gebruikt een bladwijzer-loopup en behoudt het plan voor '20130122', ondanks het feit dat eerder werd aangenomen dat een tabelscan een geschikter plan is. GetFromT2
wordt niet beïnvloed door de bestelling en heeft hetzelfde plan als vóór de hercompliateion.
Samenvattend hangt het dus af van de distributie van uw gegevens en uw indexen, uw frequentie van hercompilatie en een beetje geluk of een procedure baat zal hebben bij het gebruik van lokale variabelen. Het is zeker niet altijd hulp.
Hopelijk heb ik enig licht geworpen op het effect van het gebruik van lokale parameters, uitvoeringsplannen en het compileren van opgeslagen procedures. Als ik volledig heb gefaald, of een belangrijk punt heb gemist, vind je hier een veel uitgebreidere uitleg:
http://www.sommarskog.se/query-plan-mysteries.html