Wäre es besser, Abfragepläne zur Wiederverwendbarkeit nach Anweisungen aufzuteilen?

11

Aufgrund meiner begrenzten Kenntnisse darüber, wie Abfragepläne von Abfragen kompiliert, gespeichert und abgerufen werden, verstehe ich, dass eine Abfrage mit mehreren Anweisungen oder eine gespeicherte Prozedur ihren Abfrageplan generiert, der im Abfrageplan-Cache gespeichert wird, der von der Abfrage bei zukünftigen Ausführungen verwendet wird.

Ich denke, dieser Plan wird mit dem Abfrage-Hash aus dem Abfrageplan-Cache abgerufen. Wenn die Abfrage bearbeitet und ausgeführt wird, ist der Hash anders und es wird ein neuer Plan generiert, da im Abfrageplan-Cache kein passender Hash gefunden werden kann.

Meine Frage lautet: Wenn ein Benutzer eine Anweisung ausführt, die eine der Anweisungen in der Abfrage mit mehreren Anweisungen ist, kann er dann den relevanten Teil des Abfrageplans verwenden, der sich bereits im Cache für die Abfrage mit mehreren Anweisungen befindet? Ich gehe davon aus, dass die Antwort Nein lautet, da die Hash-Werte offensichtlich nicht übereinstimmen. Wäre es jedoch besser, jede Anweisung in einer Abfrage mit mehreren Anweisungen zu hashen, damit sie von Benutzern verwendet werden können, die einzelne Anweisungen aus der Abfrage ausführen?

Ich gehe davon aus, dass es Komplikationen gibt, die ich nicht berücksichtige (und über diese möchte ich wirklich Bescheid wissen), aber es scheint, als könnten wir denselben "Anweisungsplan" in vielen Abfrageplänen speichern, die mehr Platz beanspruchen und mehr beanspruchen CPU und Zeit zum Generieren.

Könnte aber nur meine Unwissenheit zeigen.

James Anderson
quelle
dbidund objectidbeide haben, is_cache_key=1so dass Sie keine Wiederverwendung von Plänen zwischen verschiedenen kompilierten Objekten erhalten.
Martin Smith

Antworten:

11

Wenn ein Benutzer eine Anweisung ausführt, die eine der Anweisungen in der Abfrage mit mehreren Anweisungen ist, kann er dann den relevanten Teil des Abfrageplans verwenden, der sich bereits im Cache für die Abfrage mit mehreren Anweisungen befindet?

Nein. Die Grundeinheit für die Wiederverwendung von Plänen in SQL Server ist der Stapel .

Wäre es besser, jede Anweisung in einer Abfrage mit mehreren Anweisungen zu hashen, damit sie von Benutzern verwendet werden können, die einzelne Anweisungen aus der Abfrage ausführen?

Ein System, das auf ein hohes Maß an Wiederverwendung von Plänen abgestimmt ist, platziert allgemeinen Code (mit einer geeigneten Granularität) in wiederverwendbaren Objekten (z. B. Prozeduren, Funktionen, Trigger) auf dem SQL Server. Außerdem werden anwendungsgenerierte oder clientseitige Codes explizit parametrisiert. Für eine maximale Wiederverwendung des Plans sollten sich diese generierten Chargen nur in den Parameterwerten unterscheiden.

Ich gehe davon aus, dass es Komplikationen gibt, die ich nicht berücksichtige

Es hört sich so an, als würden Sie fragen, warum SQL Server so konzipiert wurde, dass es auf Stapelebene und nicht auf Anweisungsebene zwischengespeichert und wiederverwendet wird. Ich bezweifle, dass jemand außer den ursprünglichen Designern diese Frage maßgeblich beantworten kann. Wie auch immer, es scheint mir, dass eine Charge eine natürliche Granularität ist, da sie eine relativ eigenständige natürliche Arbeitseinheit darstellt und einen vernünftigen Kompromiss zwischen der Komplexität der Implementierung und der Wahrscheinlichkeit der Wiederverwendung von Plänen darstellt.

Es gibt einige Dinge, die dazu führen, dass Stapel nicht vollständig in sich geschlossen sind (z. B. lokale temporäre Tabellen, die über Grenzen gespeicherter Prozeduren hinweg erstellt und referenziert werden). Diese Ausnahmen verringern die Orthogonalität und wurden im Laufe der Jahre mit unerwarteten Verhaltensweisen und Fehlern in Verbindung gebracht.

Paul White 9
quelle