SQL server – Erstellen eines Plan-Handbuchs ohne Verwendung eines Alias

Ich versuche, einen Plan-Guide in SQL server 2012 SP3 Enterprise Edition für eine bestimmte Abfrage von einer Anwendung ausgeführt, was bedeutet, ich kann nicht ändern, die Abfrage in irgendeiner Weise zu erstellen.

Die Abfrage sieht so aus:

(@P1 nvarchar(5),@P2 bigint) DELETE FROM INVENTSUMDELTA WHERE ((DATAAREAID=@P1) AND (TTSID=@P2)) 

Um die Plan-Anleitung zu erstellen, habe ich die folgende Abfrage verwendet:

 EXEC sp_create_plan_guide @name = N'INVENTSUMDELTAINDEX', @stmt = N'DELETE FROM INVENTSUMDELTA WHERE ((DATAAREAID=@P1) AND (TTSID=@P2))', @type = N'SQL', @module_or_batch = NULL, @params = N'@P1 nvarchar(5),@P2 bigint', @hints = N'OPTION (TABLE HINT ( INVENTSUMDELTA, INDEX( I_2397TTSDIMIDX )))'; 

Allerdings erhielt ich einen Fehler:

Msg 8724, Ebene 16, Status 1, Zeile 1 Kann keine Abfrage ausführen. Die tabellarische oder OPENROWSET-function 'INVENTSUMDELTA' kann in der TABLE HINT-Klausel nicht angegeben werden.

Ich habe die Dokumentation überprüft und folgendes gefunden:

TABLE HINT (exposed_object_name [, [[,] … n]]) Wendet den angegebenen Tabellenhinweis auf die Tabelle oder die view an, die dem exposed_object_name entspricht. […]

exposed_object_name kann eine der folgenden referenceen sein:

  • Wenn ein Alias ​​für die Tabelle oder die view in der FROM-Klausel der Abfrage verwendet wird, ist exposed_object_name der Alias.

  • Wenn ein Alias ​​nicht verwendet wird, ist exposed_object_name die exakte Übereinstimmung der Tabelle oder der view, auf die in der FROM-Klausel verwiesen wird. Wenn z. B. die Tabelle oder die view mit einem zweiteiligen Namen referenziert wird, ist exposed_object_name der gleiche zweiteilige Name.

Daraus sammle ich, dass es möglich sein sollte, einen Planführer für eine Abfrage zu erstellen, die keinen Alias ​​verwendet. Allerdings kann ich es nicht zur Arbeit bringen.

Also meine Frage ist: Wie erstelle ich einen Planführer ohne Aliasing und ohne die ursprüngliche Abfrage zu verändern?

Die Fehlermeldung ist irreführend. Es hat nichts mit der Natur des objects zu tun (Sie erhalten den gleichen Fehler mit einem nicht vorhandenen object). Das Problem ist, dass es nicht für DELETE statementen funktionieren wird – jeder TABLE HINT sich auf eine Tabelle bezieht, die das Ziel eines DELETE wird diesen Fehler erzeugen. Dies ist nicht darauf beschränkt, Führer zu planen – ein einfaches DELETE mit einer Option scheitert auch:

 DELETE FROM does_not_exist OPTION (TABLE HINT (does_not_exist, INDEX (does_not_exist))) 

Kann keine Abfrage ausführen. Die tabellarische oder OPENROWSET-function 'does_not_exist' kann in der TABLE HINT-Klausel nicht angegeben werden.

Dies scheint ein Fehler zu sein, denn wenn die statement mit einem WITH (ROWLOCK) Hinweis auf die Tabelle und die Abfrageebene erweitert wird, verschwindet der Fehler:

 DELETE FROM does_not_exist WITH (ROWLOCK) OPTION (TABLE HINT (does_not_exist, ROWLOCK, INDEX (does_not_exist))) 

Ungültiger objectname 'does_not_exist'.

Das gleiche Problem wird in dieser Frage abgedeckt, und die Lösung ist, die Abfrage in einer Form umzuschreiben, die die Anwendung des Hinweises erlaubt.

In diesem Fall können wir die Abfrage nicht direkt umschreiben, aber wir können immer noch den gewünschten Effekt erhalten, indem wir einen festen Abfrageplan verwenden :

 -- Alternate query using hint. DECLARE @sql NVARCHAR(MAX) = N'WITH T AS ( SELECT * FROM INVENTSUMDELTA WITH (INDEX (I_2397TTSDIMIDX)) WHERE ((DATAAREAID=@P1) AND (TTSID=@P2)) ) DELETE T'; DECLARE @params NVARCHAR(MAX) = N'@P1 nvarchar(5),@P2 bigint' -- Put the execution plan in the cache. EXEC sp_executesql @sql, @params = @params, @P1=NULL, @P2=NULL; -- Retrieve it. DECLARE @query_plan NVARCHAR(MAX); SELECT @query_plan = query_plan FROM sys.dm_exec_query_stats AS qs CROSS APPLY sys.dm_exec_sql_text(qs.[sql_handle]) AS st CROSS APPLY sys.dm_exec_text_query_plan(qs.[plan_handle], DEFAULT, DEFAULT) AS qp WHERE st.[text] LIKE '(' + @params + ')%' + @sql; -- Create a plan guide associating the query with the new execution plan. EXEC sp_create_plan_guide @name = N'INVENTSUMDELTAINDEX', @stmt = N'DELETE FROM INVENTSUMDELTA WHERE ((DATAAREAID=@P1) AND (TTSID=@P2))', @type = N'SQL', @module_or_batch = NULL, @params = @params, @hints = @query_plan; 

Wie immer sollten Planführer das letzte Resort sein, wenn nichts anderes hilft (Aktualisierung von Statistiken, Erstellen neuer Indizes, Ablegen von suboptimalen Indizes). Diese Antwort geht davon aus, dass Sie alle anderen Optionen überprüft haben und die Planführung notwendig ist.