Schemaqualifizierung für die Wiederverwendung des Abfrageplans erforderlich?

7

Beim Lesen dieses Artikels über Plan-Caching in SQL Server stieß ich auf einen Leckerbissen, den ich nicht kannte:

... für die Wiederverwendung ist es erforderlich, dass die Objekte, auf die der Stapel verweist, keine Namensauflösung erfordern. Beispielsweise erfordert Sales.SalesOrderDetail keine Namensauflösung, während SalesOrderDetail dies tut, da in mehreren Schemas Tabellen mit dem Namen SalesOrderDetail vorhanden sein können. Im Allgemeinen bieten zweiteilige Objektnamen (dh schema.object) mehr Möglichkeiten für die Wiederverwendung von Plänen.

Ich suche nach einer Klarstellung darüber, wie wichtig es ist, zweiteilige Objektnamen zu verwenden, da "zweiteilige Objektnamen im Allgemeinen mehr Möglichkeiten für die Wiederverwendung von Plänen bieten". Zunächst wird jedoch darauf hingewiesen, dass dies erforderlich ist.

Insbesondere befinden sich die meisten gespeicherten Prozeduren, mit denen ich mich befasse, im dbo-Schema und verweisen nur auf dbo-Objekte, ohne das dbo-Präfix anzugeben. Werden diese daran gehindert, zwischengespeicherte Abfragepläne wiederzuverwenden, selbst wenn alles das Standardschema verwendet?

Bort
quelle

Antworten:

7

Damit ein Plan wiederverwendet werden kann, müssen alle Attribute in sys.dm_exec_plan_attributeswo is_cache_key=1gleich sein. Eine Liste davon finden Sie unten.

acceptable_cursor_options
compat_level
date_first
date_format
dbid
dbid_execute
is_replication_specific
language_id
merge_action_type
objectid
optional_clr_trigger_dbid
optional_clr_trigger_objid
optional_spid
required_cursor_options
set_options
status
user_id

Derjenige, der von der Verwendung von zwei Teilenamen betroffen ist, ist user_id

Wenn Sie unter den Anmeldeinformationen eines Benutzers mit Standardschema Folgendes versuchen dbo

DBCC FREEPROCCACHE;

CREATE TABLE dbo.FooBar(X int);

EXEC('SELECT * FROM FooBar');
EXEC('SELECT * FROM FooBar');

EXEC('SELECT * FROM dbo.FooBar');
EXEC('SELECT * FROM dbo.FooBar');

Führen Sie dann die folgende Abfrage aus

SELECT usecounts,
       text,
       value AS [user_id] 
FROM sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
CROSS APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
WHERE text LIKE 'SELECT * FROM %FooBar'  and attribute='user_id'

Sie sehen die folgenden Ergebnisse

usecounts   text                                user_id
----------- ----------------------------------- -------
2           SELECT * FROM dbo.FooBar            -2
2           SELECT * FROM FooBar                1 

Dies zeigt, dass beide Pläne wiederverwendet wurden, als die identische Anweisung zum zweiten Mal ausgeführt wurde. Die Dokumente für sys.dm_exec_plan_attributes erklären für dieuser_id

Der Wert -2 gibt an, dass der übermittelte Stapel nicht von der impliziten Namensauflösung abhängt und von verschiedenen Benutzern gemeinsam genutzt werden kann. Dies ist die bevorzugte Methode. Jeder andere Wert repräsentiert die Benutzer-ID des Benutzers, der die Abfrage in der Datenbank sendet.

Dies scheint falsch zu sein! Aus meinen Tests geht hervor, dass der Wert, den er user_idim zweiten Fall tatsächlich für verwendet schema_id, eher das Standardschema für den ausführenden Benutzer als eine Kennung für diesen bestimmten Benutzer ist. Das EXECerneute Ausführen der vier Anweisungen unter einem anderen Login mit dem Standardschema "dbo" ergibt.

usecounts   text                                user_id
----------- ----------------------------------- -------
4           SELECT * FROM dbo.FooBar            -2
4           SELECT * FROM FooBar                1 

Das Anzeigen der Pläne für beide Versionen der Abfrage konnte zwischen Benutzern wiederverwendet werden. Schließlich führen Sie die vier EXECAnweisungen erneut unter einem dritten Login mit dem Standardschema "guest" aus.

usecounts   text                                user_id
----------- ----------------------------------- -------
6           SELECT * FROM dbo.FooBar            -2
4           SELECT * FROM FooBar                1
2           SELECT * FROM FooBar                2

Es wurde angezeigt, dass der Plan für die dboqualifizierte Abfrage erfolgreich von Benutzern mit unterschiedlichen Standardschemata gemeinsam genutzt wurde, für die nicht schemaqualifizierte Abfrage jedoch ein neuer Plan kompiliert werden musste.

Wenn Sie nicht über diese gemeinsame Nutzung sehen geschieht sicher , dass alle Anmeldungen Sie testen werden , haben die gleiche set_options, language_id, date_first, date_formatwie diese unter den Cache - Schlüssel sind am Anfang aufgelistet und alle Unterschiede in denen werden die Pläne verhindern zwischen den Sitzungen wiederverwendet werden.

Martin Smith
quelle
@Bort - Eigentlich habe ich gerade festgestellt, dass es vom Standardschema abhängt, nicht nur vom user_id. In meinem ursprünglichen Test hatte ich den zweiten Benutzer WITH DEFAULT_SCHEMA=[guest]. Solange zwei verschiedene Benutzer dasselbe Standardschema haben, können sie sich anscheinend gegenseitig die Pläne teilen.
Martin Smith