(Frage von SO verschoben)
Ich habe eine Tabelle (Dummy-Daten) mit Clustered-Index enthält 2 Spalten:
Jetzt führe ich diese beiden Abfragen aus:
declare
@productid int =1 ,
@priceid int = 1
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid OR @productid IS NULL)
AND (priceid = @priceid OR @priceid IS NULL)
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid)
AND (priceid = @priceid)
Der tatsächliche Ausführungsplan für beide Abfragen lautet:
Wie Sie sehen können, verwendet der erste SCAN, während der zweite SEEK verwendet.
Durch Hinzufügen OPTION (RECOMPILE)
zur ersten Abfrage wurde der Ausführungsplan jedoch auch zur Verwendung von SEEK:
Freunde im DBA-Chat sagten mir:
In Ihrer Abfrage ist @ productid = 1, was bedeutet, dass (productID = @ productID ODER @productID IS NULL) zu (productID = @ productID) vereinfacht werden kann. Ersteres erfordert einen Scan, um mit einem beliebigen Wert von @productID zu arbeiten, letzteres könnte eine Suche verwenden. Wenn Sie also RECOMPILE verwenden, überprüft SQL Server, welchen Wert Sie tatsächlich in @productID haben, und erstellt den besten Plan dafür. Mit einem Wert ungleich Null in @productID ist eine Suche am besten. Wenn der Wert von @productID unbekannt ist, muss der Plan einem beliebigen Wert in @productID entsprechen, für den ein Scan erforderlich wäre. Seien Sie gewarnt: OPTION (RECOMPILE) erzwingt bei jeder Ausführung eine Neukompilierung des Plans, wodurch jeder Ausführung einige Millisekunden hinzugefügt werden. Dies ist jedoch nur dann ein Problem, wenn die Abfrage sehr häufig ausgeführt wird.
Ebenfalls :
Wenn @productID null ist, welchen Wert würden Sie suchen? Antwort: Es gibt nichts zu suchen. Alle Werte qualifizieren sich.
Ich verstehe, dass OPTION (RECOMPILE)
SQL Server gezwungen ist, zu sehen, welche tatsächlichen Werte die Parameter haben, und zu prüfen, ob es damit suchen kann.
Aber jetzt verliere ich den Vorteil der Vorauskompilierung.
Frage
IMHO - SCAN wird nur ausgeführt, wenn ein Parameter null ist.
Das ist in Ordnung - lassen Sie SQL SERVER einen Ausführungsplan für SCAN erstellen.
ABER wenn SQL Server sieht, dass ich diese Abfrage viele Male mit Werten 1,1
ausführe : Warum erstellt es dann keinen weiteren Ausführungsplan und verwendet dafür SEEK?
AFAIK - SQL erstellt einen Ausführungsplan für die am häufigsten getroffenen Abfragen .
Warum speichert SQL SERVER keinen Ausführungsplan für:
@productid int =1 , @priceid int = 1
(Ich führe es viele Male mit diesen Werten aus)
- Ist es möglich, SQL zu zwingen, diesen Ausführungsplan (der SEEK verwendet) für zukünftige Aufrufe beizubehalten?