Database
 sql >> Datenbank >  >> RDS >> Database

Fortsetzung der Summer Performance Palooza 2013

Am 27. Juni veranstaltete das PASS Performance Virtual Chapter sein Summer Performance Palooza 2013 – eine Art abgespecktes 24-Stunden-PASS, das sich jedoch ausschließlich auf leistungsbezogene Themen konzentrierte. Ich habe eine Sitzung mit dem Titel „10 schlechte Gewohnheiten, die die Leistung zerstören können“ gegeben, in der die folgenden 10 Konzepte behandelt wurden:

  1. AUSWÄHLEN *
  2. Blind-Indizes
  3. Kein Schemapräfix
  4. Standard-Cursor-Optionen
  5. sp_ Präfix
  6. Cache-Bloat zulassen
  7. Breite Datentypen
  8. SQL Server-Standardeinstellungen
  9. Überbeanspruchung von Funktionen
  10. "Funktioniert auf meinem Rechner"

Sie erinnern sich vielleicht an einige dieser Themen aus Präsentationen wie meinem Vortrag „Bad Habits and Best Practices“ oder unseren wöchentlichen Query Tuning-Webinaren, die ich mit Kevin Kline von Anfang Juni bis diese Woche veranstaltet habe. (Diese 6 Videos werden übrigens Anfang August auf YouTube verfügbar sein.)

Meine Sitzung hatte 351 Teilnehmer und ich bekam großartiges Feedback. Einiges davon wollte ich ansprechen.

Zuerst ein Konfigurationsproblem:Ich benutzte ein brandneues Mikrofon und hatte keine Ahnung, dass jeder Tastendruck wie Donner klingen würde. Ich habe dieses Problem durch eine bessere Platzierung meiner Peripheriegeräte behoben, aber ich möchte mich bei allen entschuldigen, die davon betroffen sind.

Als nächstes die Downloads; Das Deck und die Proben werden auf der Veranstaltungsseite veröffentlicht. Sie befinden sich unten auf der Seite, aber Sie können sie auch gleich hier herunterladen.

Abschließend folgt eine Liste mit Fragen, die während der Sitzung gepostet wurden, und ich wollte sicherstellen, dass ich alle angesprochen habe, die während der Live-Fragen und Antworten nicht beantwortet wurden. Ich entschuldige mich dafür, dass ich dies in knapp einem Monat hineingequetscht habe , aber es waren viele Fragen, und ich wollte sie nicht in Teilen veröffentlichen.

F:Wenn Sie eine Prozedur haben, die stark variierende Eingabewerte für die angegebenen Parameter haben kann und das Ergebnis darin besteht, dass der zwischengespeicherte Plan für die meisten Fälle nicht optimal ist, ist es am besten, die Prozedur WITH RECOMPILE zu erstellen und die kleine zu nehmen Performance-Hit bei jeder Ausführung?

A: Sie müssen dies von Fall zu Fall angehen, da es wirklich von einer Vielzahl von Faktoren abhängt (einschließlich der Komplexität des Plans). Beachten Sie auch, dass Sie eine Neukompilierung auf Anweisungsebene durchführen können, sodass nur die betroffenen Anweisungen den Treffer erhalten müssen, im Gegensatz zum gesamten Modul. Paul White erinnerte mich daran, dass Leute das Parameter-Sniffing oft mit RECOMPILE „reparieren“. , aber allzu oft bedeutet das WITH RECOMPILE im Stil von 2000 statt der viel besseren OPTION (RECOMPILE) , die sich nicht nur auf die Anweisung beschränkt, sondern auch die Einbettung von Parametern ermöglicht, die WITH RECOMPILE nicht. Wenn Sie also RECOMPILE verwenden Um Parameter-Sniffing zu verhindern, fügen Sie es der Anweisung hinzu, nicht dem Modul.

F:Wenn Sie die Option recompile für dynamisches SQL verwenden, würden Sie einen großen Leistungseinbruch sehen

A: Wie oben wird dies von den Kosten und der Komplexität der Pläne abhängen, und es gibt keine Möglichkeit zu sagen:"Ja, es wird immer einen großen Leistungseinbruch geben." Das musst du auch unbedingt mit der Alternative vergleichen.

F:Wenn am Einfügedatum ein gruppierter Index vorhanden ist, verwenden wir später beim Abrufen von Daten die Konvertierungsfunktion. Wenn der direkte Vergleich verwendet wird, ist das Abfragedatum in der realen Welt nicht lesbar, was ist die bessere Wahl

A: Ich bin mir nicht sicher, was "in der realen Welt lesbar" bedeutet. Wenn Sie die Ausgabe in einem bestimmten Format wünschen, ist es in der Regel besser, wenn Sie clientseitig in eine Zeichenfolge konvertieren. C# und die meisten anderen Sprachen, die Sie wahrscheinlich auf der Präsentationsebene verwenden, sind mehr als in der Lage, Datums-/Zeitausgaben aus der Datenbank in jedem gewünschten regionalen Format zu formatieren.

F:Wie bestimmt man, wie oft ein zwischengespeicherter Plan verwendet wird – gibt es eine Spalte mit diesem Wert oder irgendwelche Abfragen im Internet, die diesen Wert ergeben? Wären solche Zählungen schließlich nur seit dem letzten Neustart relevant?

A: Die meisten DMVs sind erst seit dem letzten Dienststart gültig, und sogar andere können häufiger geleert werden (sogar auf Anfrage – sowohl versehentlich als auch absichtlich). Der Plan-Cache ist natürlich in ständiger Bewegung, und AFAIK-Pläne, die aus dem Cache herausfallen, behalten ihre vorherige Zählung nicht bei, wenn sie wieder reinkommen. Also, selbst wenn Sie einen Plan im Cache sehen, bin ich nicht 100% zuversichtlich, dass Sie der Anzahl der Verwendungen glauben können, die Sie finden.

Das heißt, was Sie wahrscheinlich suchen, ist sys.dm_exec_cached_plans.usecounts und Sie können auch sys.dm_exec_procedure_stats.execution_count finden um Informationen für Prozeduren zu ergänzen, bei denen einzelne Anweisungen innerhalb der Prozeduren nicht im Cache gefunden werden.

F:Welche Probleme treten auf, wenn die DB-Engine auf eine neue Version aktualisiert wird, die Benutzerdatenbanken jedoch in älteren Kompatibilitätsmodi belassen werden?

A: Die Hauptsorgen in diesem Zusammenhang sind die Möglichkeit, eine bestimmte Syntax zu verwenden, wie z. B. OUTER APPLY oder Variablen mit einer Tabellenwertfunktion. Mir sind keine Fälle bekannt, in denen die Verwendung einer niedrigeren Kompatibilität sich direkt auf die Leistung auswirkt, aber einige Dinge, die normalerweise empfohlen werden, sind, Indizes neu zu erstellen und Statistiken zu aktualisieren (und Ihren Anbieter dazu zu bringen, die neuere Kompatibilitätsstufe so schnell wie möglich zu unterstützen). Ich habe gesehen, wie es in einer beträchtlichen Anzahl von Fällen unerwartete Leistungseinbußen behoben hat, aber ich habe auch einige Meinungen gehört, dass dies nicht notwendig und vielleicht sogar unklug ist.

F:Beim * spielt es eine Rolle, ob eine Existiert-Klausel ausgeführt wird

A: Nein, zumindest in Bezug auf die Leistung, eine Ausnahme, bei der SELECT * spielt keine Rolle, wenn es innerhalb eines EXISTS verwendet wird Klausel. Aber warum sollten Sie * verwenden? hier? Ich bevorzuge die Verwendung von EXISTS (SELECT 1 ... – Der Optimierer behandelt diese gleich, aber in gewisser Weise dokumentiert er den Code selbst und stellt sicher, dass die Leser verstehen, dass die Unterabfrage keine Daten zurückgibt (selbst wenn sie das große EXISTS übersehen). draußen). Einige Leute verwenden NULL , und ich habe keine Ahnung, warum ich angefangen habe, 1 zu verwenden, aber ich finde NULL auch etwas unintuitiv.

*Hinweis* Sie müssen vorsichtig sein, wenn Sie versuchen, EXISTS (SELECT * innerhalb eines schemagebundenen Moduls:

CREATE VIEW dbo.ThisWillNotWork
WITH SCHEMABINDING
AS
  SELECT BusinessEntityID
    FROM Person.Person AS p
	WHERE EXISTS (SELECT * FROM Sales.SalesOrderHeader AS h
	  WHERE h.SalesPersonID = p.BusinessEntityID);

Sie erhalten diesen Fehler:

Msg 1054, Level 15, State 6, Procedure ThisWillNotWork, Line 6
Syntax '*' ist in schemagebundenen Objekten nicht erlaubt.

Ändern Sie es jedoch in SELECT 1 funktioniert prima. Vielleicht ist das ein weiteres Argument dafür, SELECT * zu vermeiden auch in diesem Szenario.

F:Gibt es einen Ressourcenlink für die besten Codierungsstandards?

A: Es gibt wahrscheinlich Hunderte in einer Vielzahl von Sprachen. Wie Namenskonventionen sind Codierungsstandards eine sehr subjektive Sache. Es spielt keine Rolle, welche Konvention für Sie am besten geeignet ist; wenn Sie tbl mögen Präfixe, verrückt! Bevorzugen Sie Pascal gegenüber BigEndian, haben Sie es. Sie möchten Ihren Spaltennamen den Datentyp voranstellen, z. B. intCustomerID , ich werde dich nicht aufhalten. Wichtiger ist, dass Sie eine Konvention definieren und diese *konsequent* anwenden.

Das heißt, wenn Sie meine Meinung wollen, ich habe keinen Mangel an ihnen.

F:Kann XACT_ABORT ab SQL Server 2008 verwendet werden?

A: Ich kenne keine Pläne, XACT_ABORT zu verwerfen also sollte es weiterhin gut funktionieren. Ehrlich gesagt sehe ich das jetzt nicht mehr sehr oft verwendet, da wir TRY / CATCH haben (und THROW ab SQL Server 2012).

F:Wie wirkt sich eine Inline-Tabellenfunktion auf eine Kreuzanwendung im Vergleich zu der Skalarfunktion mit dem Namen 1.000x aus?

A: Ich habe das nicht getestet, aber in vielen Fällen kann das Ersetzen einer Skalarfunktion durch eine Inline-Tabellenwertfunktion große Auswirkungen auf die Leistung haben. Das Problem, das ich finde, ist, dass das Durchführen dieses Wechsels eine erhebliche Menge an Arbeit auf Systemen bedeuten kann, die vor APPLY geschrieben wurden existierten oder werden immer noch von Leuten verwaltet, die diesen besseren Ansatz nicht angenommen haben.

F:Ich habe eine Abfrage, die beim ersten Mal sehr langsam (ca. 1 Minute) und jedes zweite Mal schnell (ca. 3 Sekunden) ausgeführt wird. Wo soll ich beim ersten Mal nachsehen, woher das Leistungsproblem kommt?

A: Zwei Dinge fallen mir spontan ein:(1) die Verzögerung hat mit der Kompilierungszeit zu tun oder (2) die Verzögerung hat mit der Datenmenge zu tun, die geladen wird, um die Abfrage zu erfüllen, und wann sie zum ersten Mal von der Festplatte kommen muss und nicht Erinnerung. Für (1) können Sie die Abfrage im SQL Sentry Plan Explorer ausführen, und die Statusleiste zeigt Ihnen die Kompilierzeit für den ersten und die nachfolgenden Aufrufe (obwohl eine Minute dafür ziemlich übertrieben und unwahrscheinlich erscheint). Wenn Sie keinen Unterschied finden, kann es einfach an der Art des Systems liegen:nicht genügend Arbeitsspeicher, um die Datenmenge zu unterstützen, die Sie mit dieser Abfrage in Kombination mit anderen Daten, die sich bereits im Pufferpool befanden, zu laden versuchen. Wenn Sie nicht glauben, dass beides das Problem ist, prüfen Sie, ob die beiden unterschiedlichen Ausführungen tatsächlich zu unterschiedlichen Plänen führen – wenn es Unterschiede gibt, posten Sie die Pläne auf answers.sqlperformance.com und wir sehen uns das gerne an . Tatsächlich kann das Erfassen tatsächlicher Pläne für beide Ausführungen mit dem Plan-Explorer Sie in jedem Fall auch über Unterschiede bei der E/A informieren und dazu führen, dass SQL Server seine Zeit bei der ersten, langsameren Ausführung verbringt.

F:Ich bekomme Parameter-Sniffing mit sp_executesql, würde Optimize für Ad-hoc-Workloads dieses Problem lösen, da sich nur der Plan-Stub im Cache befindet?

A: Nein, ich glaube nicht, dass die Einstellung „Für Ad-hoc-Arbeitslasten optimieren“ in diesem Szenario hilfreich sein wird, da Parameter-Sniffing impliziert, dass nachfolgende Ausführungen desselben Plans für unterschiedliche Parameter und mit deutlich unterschiedlichem Leistungsverhalten verwendet werden. Optimize for ad hoc workloads wird verwendet, um die drastischen Auswirkungen auf den Plan-Cache zu minimieren, die auftreten können, wenn Sie eine große Anzahl unterschiedlicher SQL-Anweisungen haben. Es sei denn, Sie sprechen über die Auswirkungen vieler verschiedener Anweisungen, die Sie an sp_executesql senden, auf den Plan-Cache – was nicht als Parameter-Sniffing bezeichnet werden würde – ich denke, mit OPTION (RECOMPILE) zu experimentieren möglicherweise ein besseres Ergebnis erzielen, oder wenn Sie die Parameterwerte kennen, die bei einer Vielzahl von Parameterkombinationen *gute Ergebnisse erzielen, verwenden Sie OPTIMIZE FOR . Diese Antwort von Paul White bietet möglicherweise einen viel besseren Einblick.

F:Gibt es eine Möglichkeit, dynamisches SQL auszuführen und den Abfrageplan NICHT zu speichern?

A: Sicher, fügen Sie einfach OPTION (RECOMPILE) hinzu im dynamischen SQL-Text:

DBCC FREEPROCCACHE;
 
USE AdventureWorks2012;
GO
SET NOCOUNT ON;
GO
 
EXEC sp_executesql 
  N'SELECT TOP (1) * INTO #x FROM Sales.SalesOrderHeader;';
GO
EXEC sp_executesql 
  N'SELECT TOP (1) * INTO #x FROM Sales.SalesOrderDetail OPTION (RECOMPILE);'
GO
 
SELECT t.[text], p.usecounts
FROM sys.dm_exec_cached_plans AS p
CROSS APPLY sys.dm_exec_sql_text(p.[plan_handle]) AS t
WHERE t.[text] LIKE N'%Sales.' + 'SalesOrder%';

Ergebnisse:1 Zeile mit Sales.SalesOrderHeader Anfrage.

Wenn nun eine Anweisung im Batch NICHT OPTION (RECOMPILE) enthält , der Plan ist möglicherweise noch im Cache, er kann nur nicht wiederverwendet werden.

F:Können Sie stattdessen BETWEEN für das Datumsbeispiel aus #9 verwenden, wenn>=und

A: Nun, BETWEEN ist semantisch nicht äquivalent zu >= AND < , sondern >= AND <= , und optimiert und führt auf genau die gleiche Weise durch. Auf jeden Fall verwende ich BETWEEN absichtlich nicht bei Datumsbereichsabfragen – überhaupt –, weil es keine Möglichkeit gibt, daraus einen offenen Bereich zu machen. Mit BETWEEN , sind beide Enden inklusive, und dies kann abhängig vom zugrunde liegenden Datentyp sehr problematisch sein (jetzt oder aufgrund einer zukünftigen Änderung, von der Sie möglicherweise nichts wissen). Der Titel mag etwas hart erscheinen, aber ich gehe in folgendem Blogbeitrag sehr detailliert darauf ein:

Was haben BETWEEN und der Teufel gemeinsam?

F:Was macht "local fast_forward" in einem Cursor wirklich?

A: FAST_FORWARD ist eigentlich die Kurzform von READ_ONLY und FORWARD_ONLY . Folgendes tun sie:

  • LOCAL macht es so, dass äußere Bereiche (standardmäßig ist ein Cursor GLOBAL es sei denn, Sie haben die Option auf Instanzebene geändert).
  • READ_ONLY macht es so, dass Sie den Cursor nicht direkt aktualisieren können, z. mit WHERE CURRENT OF .
  • FORWARD_ONLY verhindert das Scrollen, z.B. unter Verwendung von FETCH PRIOR oder FETCH ABSOLUTE statt FETCH NEXT .

Das Festlegen dieser Optionen kann, wie ich demonstriert habe (und darüber gebloggt habe), erhebliche Auswirkungen auf die Leistung haben. Sehr selten sehe ich Cursor in der Produktion, die tatsächlich von diesem Satz von Funktionen abweichen müssen, aber normalerweise sind sie so geschrieben, dass sie die viel teureren Standardeinstellungen akzeptieren.

F:Was ist effizienter, ein Cursor oder eine While-Schleife?

A: Ein WHILE loop wird wahrscheinlich effizienter sein als ein äquivalenter Cursor mit den Standardoptionen, aber ich vermute, dass Sie kaum einen Unterschied feststellen werden, wenn Sie LOCAL FAST_FORWARD verwenden . Im Allgemeinen ein WHILE loop *ist* ein Cursor, ohne als Cursor bezeichnet zu werden, und letztes Jahr habe ich einige hochgeschätzte Kollegen herausgefordert, mir das Gegenteil zu beweisen. Ihr WHILE Schleifen schnitten nicht so gut ab.

F:Sie empfehlen kein usp-Präfix für gespeicherte Benutzerprozeduren, hat dies die gleichen negativen Auswirkungen?

A: Ein usp_ Präfix (oder ein anderes Präfix als sp_ , oder kein Präfix für diese Angelegenheit) hat *nicht* die gleiche Wirkung, die ich demonstriert habe. Ich finde es jedoch wenig sinnvoll, ein Präfix für gespeicherte Prozeduren zu verwenden, da es sehr selten Zweifel gibt, wenn ich Code finde, der EXEC something sagt , dass etwas eine gespeicherte Prozedur ist – daher hat es wenig Wert (anders als beispielsweise Ansichten voranzustellen, um sie von Tabellen zu unterscheiden, da sie austauschbar verwendet werden können). Wenn Sie jeder Prozedur das gleiche Präfix geben, wird es auch viel schwieriger, das gesuchte Objekt beispielsweise im Objekt-Explorer zu finden. Stellen Sie sich vor, jedem Nachnamen im Telefonbuch würde LastName_ vorangestellt – inwiefern hilft dir das weiter?

F:Gibt es eine Möglichkeit, zwischengespeicherte Pläne zu bereinigen, wenn mehrere Kopien vorhanden sind?

A: Ja! Nun, wenn Sie SQL Server 2008 oder höher verwenden. Sobald Sie zwei identische Pläne identifiziert haben, haben sie immer noch separate plan_handle Werte. Identifizieren Sie also denjenigen, den Sie *nicht* behalten möchten, und kopieren Sie dessen plan_handle , und fügen Sie es in diesen DBCC ein Befehl:

DBCC FREEPROCCACHE(0x06.....);
F:Verursacht die Verwendung von if else usw. in einer Prozedur schlechte Pläne, wird sie für den ersten Lauf optimiert und nur für diesen Pfad optimiert? Müssen also die Codeabschnitte in jedem IF in separate Prozeduren umgewandelt werden?

A: Da SQL Server nun eine Optimierung auf Anweisungsebene durchführen kann, hat dies heute weniger drastische Auswirkungen als bei älteren Versionen, bei denen die gesamte Prozedur als eine Einheit neu kompiliert werden musste.

F:Ich habe manchmal festgestellt, dass das Schreiben von dynamischem SQL besser sein kann, weil es das Parameter-Sniffing-Problem für sp eliminiert. Ist das wahr ? Müssen bei diesem Szenario Kompromisse oder andere Überlegungen angestellt werden?

A: Ja, dynamisches SQL kann das Ausspähen von Parametern häufig verhindern, insbesondere in Fällen, in denen eine massive „Küchenspüle“-Abfrage viele optionale Parameter enthält. Ich habe einige andere Überlegungen in den obigen Fragen behandelt.

F:Wenn ich eine berechnete Spalte in meiner Tabelle als DATEPART(mycolumn, year) und im Index darauf hätte, würde SQL Server diese mit einem SEEK verwenden?

A: Es sollte, aber es hängt natürlich von der Abfrage ab. Der Index ist möglicherweise nicht geeignet, um die Ausgabespalten abzudecken oder andere Filter zu erfüllen, und der von Ihnen verwendete Parameter ist möglicherweise nicht selektiv genug, um eine Suche zu rechtfertigen.

F:Wird für JEDE Abfrage ein Plan erstellt? Wird ein Plan auch für triviale generiert?

A: Soweit ich weiß, wird ein Plan für jede gültige Abfrage generiert, auch für triviale Pläne, es sei denn, es liegt ein Fehler vor, der die Generierung eines Plans verhindert (dies kann in mehreren Szenarien auftreten, z. B. bei ungültigen Hinweisen). Ob sie zwischengespeichert werden oder nicht (und wie lange sie im Cache bleiben), hängt von einer Vielzahl anderer Faktoren ab, von denen ich einige oben besprochen habe.

F:Wird durch einen Aufruf von sp_executesql der zwischengespeicherte Plan generiert (und wiederverwendet)?

A: Ja, wenn Sie genau denselben Abfragetext senden, spielt es keine Rolle, ob Sie ihn direkt ausgeben oder über sp_executesql senden , wird SQL Server den Plan zwischenspeichern und wiederverwenden.

F:Ist es in Ordnung, eine Regel (für eine Entwicklungsumgebung) durchzusetzen, in der alle Entwicklungsmaschinen die sofortige Dateiinitialisierung verwenden?

A: Ich sehe nicht, warum nicht. Die einzige Sorge, die ich hätte, ist, dass die Entwickler bei der sofortigen Dateiinitialisierung möglicherweise keine große Anzahl von Autogrowth-Ereignissen bemerken, die schlechte Autogrowth-Einstellungen widerspiegeln können, die sich sehr unterschiedlich auf die Produktionsumgebung auswirken können (insbesondere, wenn einer dieser Server dies tut *nicht * IFI aktiviert haben).

F:Wäre es bei der Funktion in der SELECT-Klausel richtig zu sagen, dass es besser ist, Code zu duplizieren?

A: Ich persönlich würde ja sagen. Ich habe viel Leistung aus dem Ersetzen von Skalarfunktionen in SELECT herausgeholt Liste mit einem Inline-Äquivalent, auch in Fällen, in denen ich diesen Code wiederholen muss. Wie oben erwähnt, können Sie jedoch in einigen Fällen feststellen, dass das Ersetzen durch eine Inline-Tabellenwertfunktion Ihnen die Wiederverwendung von Code ohne die hässlichen Leistungseinbußen ermöglicht.

F:Können wir Datengeneratoren verwenden, um die gleiche Datengröße für Entwicklungszwecke zu erhalten, anstatt (schwer erhältliche) Produktionsdaten zu verwenden? Ist die Datenverzerrung wichtig für die resultierenden Pläne?

A: Datenversatz kann einen Faktor haben, und ich vermute, dass dies davon abhängt, welche Art von Daten Sie generieren / simulieren und wie weit der Versatz entfernt sein könnte. Wenn Sie beispielsweise eine varchar(100)-Spalte haben, die in der Produktion normalerweise 90 Zeichen lang ist, und Ihre Datengenerierung Daten mit durchschnittlich 50 Zeichen erzeugt (wovon SQL Server ausgeht), werden Sie ganz andere Auswirkungen auf die Zahl feststellen von Seiten und Optimierung, und wahrscheinlich nicht sehr realistische Tests.

Aber ich bin ehrlich:In diese spezielle Facette habe ich nicht viel Zeit investiert, weil ich mich normalerweise an echte Daten herankämpfen kann. :-)

F:Sind bei der Untersuchung der Abfrageleistung alle erstellten Funktionen gleich? Wenn nicht, gibt es eine Liste bekannter Funktionen, die Sie nach Möglichkeit vermeiden sollten?

A: Nein, nicht alle Funktionen sind in Bezug auf die Leistung gleich. Es gibt drei verschiedene Arten von Funktionen, die wir erstellen können (vorerst CLR-Funktionen ignorieren):

  • Skalarfunktionen mit mehreren Anweisungen
  • Tabellenwertfunktionen mit mehreren Anweisungen
  • Inline-Tabellenwertfunktionen
    Inline-Skalarfunktionen werden in der Dokumentation erwähnt, aber sie sind ein Mythos und gelten seit SQL Server 2014 darf zumindest neben Sasquatch und dem Ungeheuer von Loch Ness erwähnt werden.

Im Allgemeinen, und wenn ich könnte, würde ich das in 80pt-Schrift schreiben, sind Inline-Tabellenwertfunktionen gut, und die anderen sollten nach Möglichkeit vermieden werden, da sie viel schwieriger zu optimieren sind.

Funktionen können auch verschiedene Eigenschaften haben, die sich auf ihre Leistung auswirken, z. B. ob sie deterministisch oder schemagebunden sind.

Bei vielen Funktionsmustern müssen Sie definitiv Überlegungen zur Leistung anstellen, und Sie sollten sich auch dieses Connect-Elements bewusst sein, das darauf abzielt, diese anzugehen.

F:Können wir laufende Summen ohne Cursors führen?

A: Ja wir können; Es gibt mehrere andere Methoden als einen Cursor (wie in meinem Blog-Beitrag, Beste Ansätze für laufende Summen – aktualisiert für SQL Server 2012):

  • Unterabfrage in SELECT-Liste
  • Rekursiver CTE
  • Selbst beitreten
  • "Skurriles Update"
  • Nur SQL Server 2012+:SUM() OVER() (unter Verwendung von default / RANGE)
  • Nur SQL Server 2012+:SUM() OVER() (unter Verwendung von ROWS)

Die letzte Option ist bei weitem der beste Ansatz, wenn Sie SQL Server 2012 verwenden. Wenn nicht, gibt es Einschränkungen für die anderen Nicht-Cursor-Optionen, die einen Cursor oft zur attraktiveren Wahl machen. Zum Beispiel ist die schrullige Update-Methode undokumentiert und es wird nicht garantiert, dass sie in der erwarteten Reihenfolge funktioniert; Der rekursive CTE erfordert, dass es keine Lücken in dem von Ihnen verwendeten sequentiellen Mechanismus gibt. und die Unterabfrage- und Self-Join-Ansätze lassen sich einfach nicht skalieren.