Vor-und Nachteile der Verwendung eines Cursors (in SQL server)
Fragte ich hier eine Frage Mit dem cursor in OLTP-Datenbanken (SQL-server)
wo die Menschen antworteten Cursor sollte niemals verwendet werden.
Ich fühle Cursor sind sehr mächtige Werkzeuge, die verwendet werden soll (ich glaube nicht, dass Microsoft unterstützt Cursor für bad Entwickler).Angenommen, Sie haben eine Tabelle, wo der Wert einer Spalte in einer Zeile ist abhängig von dem Wert der gleichen Spalte in der vorherigen Zeile. Wenn es eine Zeit, die back-end-Prozess, nicht Sie denken, mit einem cursor wäre eine akzeptable Wahl?
Aus der Spitze von meinem Kopf kann ich denken, ein paar Szenarien, wo ich finde, es sollte keine Schande Hilfe des cursors. Bitte lassen Sie mich wissen, wenn Sie die Jungs fühlen sich anders.
1>Eine einmalige back-end-Prozess zu reinigen schlechten Daten, die Ausführung innerhalb von ein paar Minuten.
2>Batch-Prozesse, die laufen einmal in eine lange Zeit (etwa einmal jährlich).
Wenn in den oben genannten Szenarien, es gibt keine sichtbaren Belastung auf die anderen Prozesse, wäre es nicht unvernünftig, zu verbringen mehr Stunden das schreiben von code zu vermeiden Cursor? In anderen Worten: in bestimmten Fällen können die Entwickler die Zeit wichtiger ist als die Leistung eines Prozesses, das hat fast keine Auswirkungen auf alles andere.
Meiner Meinung nach, würde dies einige Szenarien, in denen Sie ernsthaft versuchen sollte Sie zu vermeiden, mit einem cursor.
1>Eine gespeicherte Prozedur aufgerufen aus einer Webseite, die aufgerufen werden, sehr oft.
2>Eine SQL-Auftrag, die ausgeführt würde, mehrere Male am Tag und verbrauchen eine Menge von Ressourcen.
Ich denke, dass seine sehr oberflächlich, um eine Allgemeine Aussage wie "Cursor sollte niemals verwendet werden," ohne die Analyse der Aufgabe bei der hand und tatsächlich Wiegen Sie gegen die alternativen.
Bitte lassen Sie mich wissen, Ihre Gedanken.
- Sieht aus wie Sql Server 2012 unterstützen werden die Fall immer den Wert aus der vorherigen Zeile in einem Satz basiert, Weg.
- "Eine gespeicherte Prozedur aufgerufen, die eine web-site" ist viel zu vage. Wenn ein cursor ist die vernünftigste Wahl, um ein problem zu lösen, und die Prozedur aufgerufen werden, die von einem web-Seite...
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es mehrere Szenarien, in denen die Cursor sogar besser als die set-based-äquivalente. Laufende Summen ist der, der einem immer in den Sinn kommt - look für Itzik Worten auf, dass (und ignorieren alle, die beinhalten, SQL Server 2012, die neue windowing-Funktionen, Cursor geben ein Lauf für Ihr Geld in dieser situation).
Eines der großen Probleme, die Menschen haben mit Cursorn ist, dass Sie langsam ausführen, verwenden Sie die temporäre Speicherung, etc. Dies ist teilweise, weil die Standard-syntax ist ein globaler cursor mit allen Arten von ineffizienten Standard-Optionen. Das nächste mal, wenn Sie etwas zu tun mit einem cursor, der nicht braucht, um Dinge wie
UPDATE...WHERE CURRENT OF
(die habe ich in der Lage zu vermeiden, die meine gesamte Karriere), geben Sie ihm eine faire Chance durch Vergleich dieser zwei syntax-Optionen:In der Tat die erste version stellt einen Fehler dar, in die undokumentierte gespeicherte Prozedur dokumentierte sp_msforeachdb das macht es skip-Datenbanken, wenn der status von Datenbank-änderungen während der Ausführung. Wie ich später schrieb meine eigene version der gespeicherten Prozedur (siehe hier und hier), die sowohl die den Fehler behoben (einfach mit der letzten version der syntax oben) und fügte hinzu, mehrere Parameter zu Steuern, welche Datenbanken entschieden werden würde.
Viele Leute denken, dass eine Methode nicht einen cursor, weil es nicht sagen
DECLARE CURSOR
. Ich habe Menschen gesehen, die argumentieren, dass eine while-Schleife ist schneller als ein cursor (die ich hoffe, ich habe hier gebannt) oder mitFOR XML PATH
durchführen Gruppe Verkettung ist nicht eine versteckte cursor-Betrieb. Blick auf den plan in einer Menge von Fällen wird zeigen die Wahrheit.In vielen Fällen Cursor verwendet werden, wo auf einer Menge basiert, ist besser geeignet. Aber es gibt viele gültige Anwendungsfälle, wo eine set-basierte äquivalent ist viel komplizierter zu schreiben, für die Optimierung zu generieren, die einen plan für beide, oder nicht möglich ist (z.B. Wartungsarbeiten, wo Sie die Schleife durch die Tabellen, um Statistiken zu aktualisieren, aufrufen einer gespeicherten Prozedur wird für jeden Wert im Ergebnis, etc.). Das gleiche gilt für eine Menge von großen multi-table-Abfragen, wo der plan wird zu monströs für den Optimierer zu handhaben. In diesen Fällen kann es besser sein, einen dump einige der Zwischenergebnisse in einer temporären Struktur erste. Das gleiche gilt für einige set-basierten äquivalenten der Cursor (wie laufende Summen). Ich hab auch geschrieben über den anderen Weg, wo die Menschen fast immer denke, instinktiv mit einer while-Schleife /cursor und es gibt clevere set-basierte alternativen, die sind viel besser.
UPDATE 2013-07-25
Wollte nur hinzufügen, einige zusätzliche blog-posts habe ich geschrieben über die Cursor, welche Optionen Sie verwenden sollten, wenn Sie tun haben, Sie zu nutzen, und mithilfe von set-basierten Abfragen anstelle von Schleifen zu erzeugen setzt:
Beste Ansätze für Laufende Summen - Aktualisiert für SQL Server 2012
Welche Auswirkungen können verschiedene cursor-Optionen haben?
Generieren einen Satz oder eine Sequenz Ohne Schleifen: [Teil 1] [Teil 2] [Teil 3]
Das Problem mit Cursor in SQL Server ist, dass der Motor eingestellt ist-basiert intern, im Gegensatz zu anderen DBMS wie Oracle, die cursor-basiert intern. Dies bedeutet, dass, wenn Sie einen cursor erstellen, in SQL-Server, temporäre Lagerung erstellt werden muss und die set-basierte resultset kopiert werden muss-auch über den temporären cursor-Speicher. Sie können sehen, warum dies wäre teuer rechts von der Fledermaus, nicht zu erwähnen, jede Zeile-für-Zeile verarbeiten, dass Sie dadurch auf der Oberseite der cursor selbst. Die Quintessenz ist, dass die set-basierte Bearbeitung ist effizienter, und oft sind Ihre cursor-basierte operation kann getan werden, besser mit einem CTE-oder temporäre Tabelle.
That being said, es gibt Fälle, in denen ein cursor ist wohl akzeptabel, wie Sie sagte, für ein-aus-Operationen. Die häufigste Verwendung ich denken kann, ist in einem Wartungsplan, wo man kann Durchlaufen alle Datenbanken auf einem server ausführen der verschiedenen Wartungsarbeiten. Solange Sie beschränken Sie Ihre Verwendung und die nicht die ganze design-Anwendungen um RBAR (Zeile-für-trauernde-Zeile) die Verarbeitung, Sie sollten in Ordnung sein.
Im Allgemeinen Cursor sind eine schlechte Sache. Aber in manchen Fällen ist es praktischer, verwenden Sie einen cursor und in einigen ist es sogar schneller ein. Ein gutes Beispiel ist ein cursor über eine Tabelle "Kontakt" senden von E-Mails basierend auf einigen Kriterien. (Nicht zu öffnen mit der Frage, ob das senden einer E-Mail von Ihrem DBMS ist eine gute Idee - lasst uns einfach annehmen, dass es für das problem zur hand.) Es gibt keine Möglichkeit zu schreiben, dass die set-basiert. Sie könnte verwenden einige Tricks, um mit einem Satz-basierende Lösung für die Generierung von dynamischen SQL, aber eine echte set-basierte Lösung existiert nicht.
Jedoch eine Berechnung im Zusammenhang mit der vorherigen Zeile gemacht werden kann mit einem self-join. Das ist in der Regel immer noch schneller als ein cursor.
In allen Fällen, die Sie benötigen, um die balance der Aufwand bei der Entwicklung einer schnelleren Lösung. Wenn niemand kümmert sich, wenn Sie Prozess läuft in 1 minute oder in einer Stunde, verwenden Sie, was bekommt den job getan Schnellste. Wenn Sie die Schleife durch ein dataset, das wächst im Laufe der Zeit wie ein [Bestellungen] Tabelle, versuchen zu bleiben Weg von einem cursor, wenn möglich. Wenn Sie nicht sicher sind, machen Sie einen performance-test, Vergleich zwischen einer cursor-Basis mit einem Satz-basierte Lösung, die auf mehrere deutlich unterschiedliche Daten, Größen.
Sind Sie notwendig für Dinge wie dynamische SQL-schwenkbare, aber Sie sollten versuchen zu vermeiden und verwenden Sie Sie, Wann immer möglich.
Hatte ich immer mochte, Cursor, die aufgrund Ihres langsamen performance. Allerdings fand ich, dass ich nicht vollständig verstehen, die verschiedenen Arten von Cursorn und dass in bestimmten Fällen die Cursor sind eine praktikable Lösung.
Wenn Sie ein business-problem, das nur gelöst werden kann, durch die Verarbeitung einer Zeile zu einem Zeitpunkt, dann einen cursor angemessen ist.
So um die Leistung zu verbessern mit dem cursor, ändern Sie die Art von cursor, die Sie verwenden. Etwas, was ich nicht wusste war, wenn Sie nicht angeben, welche Art von cursor, die Sie deklarieren, erhalten Sie die Dynamische Optimistisch geben standardmäßig, das ist die eine, die ist die langsamste, für die performance, denn es macht viel Arbeit unter der Haube. Jedoch, indem er den cursor als eine andere Art, sagen wir einen statischen cursor, es hat eine sehr gute Leistung.
Siehe diesen Artikel für eine ausführlichere Erklärung:
Die Wahrheit Über Cursor: Teil I
Die Wahrheit Über Cursor: Teil II
Die Wahrheit Über Cursor: Teil III
Ich denke, die größte con gegen-Cursor ist die Leistung, jedoch nicht auslegen, eine Aufgabe in einen set-basierten Ansatz würde wahrscheinlich zweiten Rang. Drittens würde die Lesbarkeit und das layout der Aufgaben, wie Sie in der Regel nicht haben eine Menge hilfreiche Kommentare.
SQL Server ist optimiert für die Ausführung der set-basierten Ansatz. Schreiben Sie die Abfrage ein ResultSet zurückgeben von Daten, wie ein join auf Tabellen für das Beispiel, aber der SQL Server execution engine bestimmt, welche join zu verwenden: Merge Join Nested-Loop-Join oder Hash Join. SQL-Server bestimmt, die beste mögliche joining-Algorithmus basiert auf der Teilnahme Spalten -, Daten-Volumen, die Indizierung der Struktur und der Menge der Werte in den beteiligten Spalten. Also mit einen set-basierten Ansatz ist in der Regel der beste Ansatz bei der Leistung über die prozessuale cursor Ansatz.