Offensichtlicher Haftungsausschluss: Ich arbeite für SQL Sentry .
Die größten Probleme, die wir haben, sind:
- Wie @JNK sagt, verschleiert SQL Server die Verwendung einer UDF und macht sowieso schreckliche Dinge mit ihnen (wie immer immer eine Zeile geschätzt). Wenn Sie einen tatsächlichen Plan in SSMS generieren, sehen Sie dessen Verwendung ebenfalls überhaupt nicht. Wir unterliegen denselben Einschränkungen, da wir nur die Informationen zu einem Plan bereitstellen können, den SQL Server uns zur Verfügung stellt.
- Bei der Erstellung eines tatsächlichen Plans stützen wir uns auf verschiedene Quellen für Laufzeitmetriken. Leider enthält das Plan-XML keine Funktionsaufrufe, und SQL Server zeigt nicht die E / A an, die bei der Verwendung einer Funktion anfallen
SET STATISTICS IO ON;
(auf diese Weise Table I/O
füllen wir unsere Registerkarte).
Betrachten Sie die folgende Ansicht und Funktion für AdventureWorks2012. Dies ist nur ein dummer Versuch, eine zufällige Zeile aus der Detailtabelle zurückzugeben, wenn eine zufällige Zeile aus der Headertabelle stammt - hauptsächlich, um sicherzustellen, dass wir jedes Mal so viel E / A wie möglich generieren.
CREATE VIEW dbo.myview
WITH SCHEMABINDING
AS
SELECT TOP (100000) rowguid, SalesOrderID, n = NEWID()
FROM Sales.SalesOrderDetail ORDER BY NEWID();
GO
CREATE FUNCTION dbo.whatever(@SalesOrderID INT)
RETURNS UNIQUEIDENTIFIER
WITH SCHEMABINDING
AS
BEGIN
RETURN
(
SELECT TOP (1) rowguid FROM dbo.myview
WHERE SalesOrderID = @SalesOrderID ORDER BY n
);
END
GO
Was Management Studio Ihnen sagt (und was nicht)
Nehmen Sie die folgende Abfrage in SSMS vor:
SET STATISTICS IO ON;
SELECT TOP (5) SalesOrderID, dbo.whatever(SalesOrderID)
FROM Sales.SalesOrderHeader ORDER BY NEWID();
SET STATISTICS IO OFF;
Wenn Sie einen Plan schätzen, erhalten Sie einen Plan für die Abfrage und einen einzelnen Plan für die Funktion (nicht 5, wie Sie vielleicht hoffen):
Sie erhalten offensichtlich überhaupt keine E / A-Daten, da die Abfrage nicht tatsächlich ausgeführt wurde. Generieren Sie nun einen aktuellen Plan. Sie erhalten die 5 Zeilen, die Sie im Ergebnisraster erwartet haben, den folgenden Plan (der die UDF absolut nicht sichtbar erwähnt, außer im XML finden Sie sie als Teil des Abfragetextes und als Teil des Skalaroperators):
Und die folgende STATISTICS IO
Ausgabe (die absolut keine Erwähnung macht Sales.SalesOrderDetail
, obwohl wir wissen , es hatte aus dieser Tabelle zu lesen):
Tabelle 'SalesOrderHeader'. Scananzahl 1, logische Lesevorgänge 57, physische Lesevorgänge 0, Vorauslesevorgänge 0, logische Vorlesevorgänge 0, physikalische Vorlesevorgänge 0, Vorlesevorgänge 0.
Was Plan Explorer Ihnen sagt
Wenn wir einen geschätzten Plan für dieselbe Abfrage erstellen, wissen wir über dasselbe Bescheid wie SSMS. Wir zeigen die Dinge jedoch etwas intuitiver. Der geschätzte Plan für die äußere Abfrage zeigt beispielsweise, wie die Ausgabe der Funktion mit der Ausgabe der Abfrage kombiniert wird, und es wird sofort - innerhalb eines einzelnen Plandiagramms - klar, dass E / A aus beiden Tabellen vorhanden sind :
Wir zeigen auch den Funktionsplan für sich , den ich nur der Vollständigkeit halber einbeziehe:
Schauen wir uns nun einen tatsächlichen Plan an, der tausendfach nützlicher ist. Der Nachteil hier ist wiederum, dass wir nur die Informationen haben, die SQL Server anzeigen möchte, sodass wir nur die grafischen Plandiagramme verfügbar machen können, die SQL Server uns zur Verfügung stellt. Dies ist keine Situation, in der wir beschlossen haben, Ihnen nichts Nützliches zu zeigen. Wir wissen eigentlich nichts darüber, basierend auf dem Plan-XML, das uns zur Verfügung gestellt wird. In diesem Fall sehen wir genau wie in SSMS nur den Plan der äußeren Abfrage und es ist, als ob die Funktion überhaupt nicht aufgerufen wird :
Auch unsere Registerkarte "Tabellen-E / A" basiert weiterhin auf der Ausgabe vonSTATISTICS IO
, wodurch auch alle im Funktionsaufruf ausgeführten Aktivitäten ignoriert werden:
Wir erhalten jedoch den gesamten Call Stack für Sie. Ich habe gelegentlich Leute fragen hören: "Pffft, wann werde ich jemals den Call Stack brauchen?" Wir können die aufgewendete Zeit, die verwendete CPU und die Anzahl der Lesevorgänge (und bei TVFs die Anzahl der erzeugten Zeilen) für jeden einzelnen Funktionsaufruf aufschlüsseln :
Leider können wir nicht korrelieren, aus welcher Tabelle (n) die E / A stammt (wiederum, weil SQL Server uns diese Informationen nicht gibt), und sie ist nicht mit dem UDF-Namen gekennzeichnet (weil es als Ad-hoc-Anweisung erfasst wird, nicht als Funktionsaufruf selbst). Aber was Sie sehen können, was Management Studio nicht tut, ist, was für ein Hund Ihre UDF ist. Sie müssen noch einige Punkte verbinden, aber es gibt weniger Punkte und sie sind näher beieinander.
Über Profiler
Schließlich würde ich dringend empfehlen, sich von Profiler fernzuhalten, es sei denn, Sie möchten einen serverseitigen Trace einrichten, den Sie außerhalb des Bereichs eines UI-Tools ausführen. Die Verwendung von Profiler gegen ein Produktionssystem wird mit ziemlicher Sicherheit mehr Probleme verursachen, als es jemals lösen wird . Wenn Sie diese Informationen erhalten möchten, verwenden Sie bitte eine serverseitige Ablaufverfolgung oder erweiterte Ereignisse und filtern Sie sehr mit Bedacht. Selbst ohne Profiler kann sich eine Ablaufverfolgung auf Ihren Server auswirken, und das Abrufen von Showplänen über erweiterte Ereignisse ist auch nicht die effizienteste Sache der Welt .