it-swarm.com.de

Ist es möglich, einen Abfrageplan aus dem Plan-Cache aus einer Datenbank in einer anderen Datenbank wiederzuverwenden?

Wenn ich beispielsweise die dynamischen Ansichten des Systems aufrufe, um einen bestimmten Abfrageplan auszuwählen, kann ich diesen Abfrageplan in den Plan-Cache einer anderen Datenbank einfügen, in dem genau dieselbe Abfrage ausgeführt wird? (Ich weiß, dass die Abfrage gehasht und verglichen wird, um festzustellen, wann ein neuer Plan erstellt werden soll. In meinem Beispiel würde ich also sicherstellen, dass die Abfrage wirklich Zeichen für Zeichen genau dieselbe ist.)

9
J.D.

Nein

Ok, das ist die Antwort auf Ihre Frage, aber Sie möchten wahrscheinlich wissen, warum.

Ok, warum nicht?

Unterschiedliche Datenbanken haben möglicherweise unterschiedliche Daten und benötigen daher unterschiedliche Pläne.

Angenommen, Sie stellen die WideWorldImporters -Datenbank zweimal auf demselben Server wieder her [~ # ~] [~ # ~] (Nennen wir es WWI_1 Und WWI_2). Sie haben zwei identische Datenbanken. SQL Server könnte möglicherweise einen Plan erstellen und ihn in Abfragen für beide Datenbanken verwenden.

Das Problem ist jedoch, dass in dem Moment, in dem diese beiden Datenbanken online gehen, ihre "Gleichheits" -Gabeln. Sie können unabhängig voneinander geändert werden. Selbst wenn sie dasselbe Schema beibehalten, können sich ihre Daten unabhängig voneinander ändern. Daher muss SQL Server die Datenbanken beim Kompilieren von Plänen unabhängig berücksichtigen. WWI_1 Kann andere Statistiken als WWI_2 Haben, was zu unterschiedlichen Plänen führen kann. Damit SQL Server für beide Datenbanken denselben Plan verwenden kann, muss SQL Server die Unterschiede nach dem Verzweigen nachverfolgen. Dies wäre komplizierter und teurer als nur das Kompilieren/Verwalten separater Pläne.

Nehmen wir ein Beispiel aus der Praxis

Stellen wir uns vor, Sie sind ein Softwareunternehmen und Host-Software für Ihre Kunden. Jeder Kunde erhält eine eigene Datenbank. In Ihrer Hosting-Umgebung befinden sich möglicherweise Hunderte von Datenbanken auf jedem Server, wobei jede Datenbank ein identisches Schema aufweist, die Daten jedoch für jeden Client eindeutig sind.

Ein Kunde hat einen Kundenstamm mit 95% kalifornischen Kunden. Das Abfragen der Adresstabelle für alle Kunden in Kalifornien würde zu einer Tabelle scan führen.

-- For CustomerA this query returns 95% of the table, so it scans
SELECT CustomerID
FROM dbo.Addresses
WHERE StateCode = 'CA';

Ein anderer Kunde hat einen Kundenstamm, der gleichmäßig über alle US-Bundesstaaten verteilt ist, und ein bedeutendes internationales Geschäft. Ein vergleichsweise geringer Prozentsatz der Kunden kommt aus Kalifornien. In diesem Fall würde das Abfragen der Adresstabelle für alle Kunden in Kalifornien zu einer Tabelle seek führen.

-- For CustomerB this query returns <1% of the table, so it seeks
SELECT CustomerID
FROM dbo.Addresses
WHERE StateCode = 'CA';

Identische Abfragen in Datenbanken mit identischem Schema mit radikal unterschiedlichen Plänen aufgrund unterschiedlicher Statistiken. Selbst wenn diese beiden Datenbanken ursprünglich aus derselben Quellensicherung wiederhergestellt wurden, muss SQL Server separate Pläne kompilieren.

Es reicht nicht aus, dass die beiden Abfragen zu 100% identisch sind und das Schema zu 100% identisch ist. Ein wiederverwendeter Plan, der nur auf diesen Kriterien basiert, kann sehr falsch sein - und SQL Server wird dies daher nicht tun.

Könnten Sie es tun, wenn Sie wirklich wollten?

Äh ... irgendwie.

Verwenden wir das gleiche Beispiel "Sie sind ein Softwareunternehmen und Host-Software für Ihre Kunden". Sie möchten den gleichen Plan für jede gehostete Datenbank erzwingen , unabhängig davon, was SQL Server tun möchte. Sie können eine Plananleitung verwenden und dieselbe Anleitung auf jede einzelne Datenbank auf dem Server anwenden. Dies ist nicht ganz dasselbe wie "[einen] Abfrageplan in den Plan-Cache einer anderen Datenbank einfügen" ... aber es wäre praktisch dasselbe.

Was ist mit einem völlig trivialen Plan?

So etwas wie SELECT COUNT(*) FROM dbo.SomeTable wäre einfach genug, um denselben Plan für beide Datenbanken zu verwenden, oder? Nein, auch dann nicht!

Lassen Sie uns ein Beispiel erstellen:

  • Erstellen Sie eine Beispieldatenbank
  • Erstellen Sie eine Tabelle und füllen Sie sie mit einigen Daten
    • Beachten Sie, dass die Tabelle eine Clustered PK und einen Nicht-Clustered-Index enthält
  • Sichern und Wiederherstellen einer zweiten Kopie auf demselben Server

Hier ist ein Code, um das zu tun:

CREATE DATABASE Sample1;
GO

USE Sample1
GO

CREATE TABLE dbo.SomeTable (
    SomeID int IDENTITY(1,1) PRIMARY KEY CLUSTERED,
    StuffType int,
    OtherStuff varchar(100),
    INDEX OtherStuff(OtherStuff)
);
GO

SET NOCOUNT ON;
INSERT INTO dbo.SomeTable (StuffType,OtherStuff)
SELECT  object_id%50,
        name 
FROM sys.objects;
GO 1000


BACKUP DATABASE Sample1 TO DISK = '/var/opt/mssql/data/Sample1.bak' WITH INIT;


RESTORE DATABASE Sample2 FROM DISK = '/var/opt/mssql/data/Sample1.bak'
    WITH MOVE 'Sample1' TO '/var/opt/mssql/data/Sample2.mdf',
         MOVE 'Sample1_log' TO '/var/opt/mssql/data/Sample2_log.ldf';

Lassen Sie uns nun diese COUNT(*) - Abfrage durchführen. Gleicher Plan für beide? Ja! Auf meinem Laptop führt es die Zählung durch, indem es die gruppierte PK scannt QueryPlansScanningPK

SQL Server scannt die PK, weil sie kleiner ist. Der nicht gruppierte Index ist größer, da er stark fragmentiert ist.

Jetzt erfolgt die Indexpflege in der Datenbank Sample1 (Nicht jedoch in der Datenbank Sample2). Jemand erstellt die Indizes für dbo.SomeTable Neu:

ALTER INDEX ALL ON Sample1.dbo.SomeTable REBUILD;

Wie wirkt sich das auf den Abfrageplan aus? (QueryPlansScanningDifferentIndexes

Auf Sample1 Ist der nicht gruppierte Index jetzt Nice & compact. Es ist kleiner als die PK. Das Scannen des nicht gruppierten Index ist die richtige Wahl für `Sample1, da er kleiner, weniger E/A-Vorgänge und schneller ist.

Bei Sample2 Ist das Scannen der PK die richtige Wahl, da sie kleiner, weniger E/A und damit schneller ist.

Identische Schemata mit identischen Daten, wobei das zweite aus einer kürzlich durchgeführten Sicherung des ersten Daten stammt. Beide Abfragen haben unterschiedliche Ausführungspläne, aber beide haben auch den Abfrageplan best für ihr Szenario.

11
AMtwo