Frage

Ich werde zuerst gehen.

Ich bin zu 100% in dem Set-Operationen Lager. Aber was passiert, wenn die eingestellte Logik auf der gesamten Domain gewünschten Eingang führt zu einem so großen Retrieval, dass die Abfrage nach unten deutlich verlangsamt, kommt zu einem Schleichen, oder nimmt im Grunde unendlich viel Zeit?

Das ist ein Fall, in dem ich eine klitzekleine Cursor (oder eine while-Schleife) von vielleicht am Dutzend von Zeilen verwenden werde (im Gegensatz zu den Millionen gegen ich Targeting). So bin ich immer noch in (partitioniert Unter-) Datensätzen arbeiten, aber mein Abruf schneller läuft.

Natürlich eine noch schnellere Lösung wäre, die partioned Eingang Domänen parallel von außen zu nennen, aber das führt eine Interaktion wird ein externes System, und wenn „gut genug“ Geschwindigkeit in Serie erreicht werden kann durch Looping, kann nur lohnt sich nicht (epecially während der Entwicklung).

War es hilfreich?

Lösung

Sicher, es gibt eine Reihe von Orten, an denen Cursor besser sein könnte als Set-basierte Operationen.

Eine davon ist, wenn Sie eine Menge von Daten in einer Tabelle zu aktualisieren (zum Beispiel eines Job SQL-Agenten aus den Vorausberechnungen Daten auf einem Zeitplan) dann könnten Sie Cursor verwenden, in mehreren kleinen Mengen zu tun, anstatt ein großen die Menge von gleichzeitiger Verriegelung zu verringern und somit die Wahrscheinlichkeit von Zugriffskonflikten und / oder Blockierungen mit anderen Prozessen Zugriff auf die Daten reduzieren.

Ein weiterer Grund ist, wenn Sie auf Anwendungsebene Sperren mit der sp_getapplock gespeicherte Prozedur nehmen wollen, was nützlich ist, wenn Sie Reihen sicherstellen möchten, dass für genau einmal durch mehrere Prozesse abgefragt werden abgerufen ( Beispiel hier ).

Im Allgemeinen aber ich würde zustimmen, dass es am besten ist, mit Satz basierte Operationen, wenn möglich zu starten, und nur Cursor bewegen, wenn entweder für Funktionalität oder Performance-Gründen erforderlich (mit Nachweis der letzteren zu sichern).

Andere Tipps

Ich habe viele Fälle, in denen Zeilen aus einer Konfigurationstabelle gelesen werden müssen und Code generiert und ausgeführt wird, oder in vielen Meta-Programmierung Szenarien.

Es gibt auch Fälle, wenn Cursor einfach übertreffen, da der Optimierer nicht intelligent genug ist. In diesen Fällen entweder gibt es Meta-Informationen in Ihrem Kopf, die einfach nicht zu dem Optimierer durch die Indizes oder Statistiken über die Tabellen aufgedeckt, oder der Code ist nur so kompliziert, dass die Verbindungen (und in der Regel wieder Joins) kann einfach ‚t in der Art und Weise optimiert werden Sie sie in einer Cursor-basierten Art und Weise zu visualisieren. In SQL Server 2005, glaube ich CTEs neigt diese viel einfacher im Code aussehen zu lassen, sondern darum, ob der Optimierer sieht sie auch als einfacher ist schwer zu wissen - es kommt auf den Ausführungsplan zu vergleichen, wie Sie denken, dass es getan werden könnte, am effizientesten und den Anruf zu machen.

Allgemeine Regel - kein Cursor wenn es unbedingt nötig. Aber wenn nötig, geben Sie nicht selbst eine harte Zeit über sie.

Es gibt viele verschiedene Cursor Verhalten .

  • STATIC vs KEYSET vs DYNAMIC
  • BLAETT vs FORWARD ONLY vs FAST FORWARD
  • INSENSITIVE oder nicht
  • OPTIMISTIC oder READ ONLY oder nicht
  • LOCAL vs GLOBAL (das ist zumindest leicht)

Sie sollten nie einen Cursor verwenden, wenn Sie können alle diese Optionen erklären und welche sind standardmäßig aktiviert .

Und ja, ich nie.

Stattdessen, wenn ich den Drang, eine Schleife über etwas in T-SQL fühlen ... Ich kann es in eine Variablentabelle laden, die so etwas wie ein LOCAL STATIC SCROLL Cursor ist ... außer dass es indiziert werden kann und verbunden ( edit:. und der Nachteil der Verwendung von Parallelität zu verhindern)

In sehr seltenen Fällen werden Sie eine Operation erhalten, die einen Cursor aber in T-SQL braucht es ist ziemlich selten. Identität (int) Spalten oder Sequenzen um die Dinge in einer Weise, innerhalb festgelegter Operationen. Aggregationen wo Berechnungen könnte an bestimmten Stellen (wie Akkumulieren Ansprüche von Masse bis zu einer Grenze oder überschüssige Punkt) für einen Cursor sind inhärent prozeduralen, so sind diejenigen ein Kandidat ändern.

Andere Kandidaten würden von Natur aus verfahren sein wie Looping durch eine Konfigurationstabelle und Erzeugen und eine Reihe von Abfragen ausgeführt werden.

Zusammen mit dem, was David B sagte, auch ich lieber die Schleife / table Ansatz.

Mit diesem aus dem Weg, ein Anwendungsfall für Cursor und die Schleife / table Ansatz extrem großes Updates beinhaltet. Angenommen, Sie 1 Milliarde Zeilen zu aktualisieren. In vielen Fällen diese müssen möglicherweise nicht transaktionale sein. Zum Beispiel könnte es eine Data Warehouse-Aggregation, in denen Sie das Potenzial haben, aus den Quelldateien zu rekonstruieren, wenn Dinge Süden gehen.

In diesem Fall kann es am besten, um das Update zu tun in „Brocken“, vielleicht 1 Million oder 10 Millionen Zeilen gleichzeitig. Dies hilft, auf ein Minimum Ressourcennutzung zu halten, und ermöglicht die gleichzeitige Verwendung der Maschine maximiert werden, während Sie, dass Milliarden Zeilen aktualisieren. Ein geschlungenen / chunked Ansatz könnte am besten hier. Milliarden Reihe Updates auf weniger als stellare Hardware neigt, Probleme zu verursachen.

In einer reinen SQL-Umgebung, würde ich eher Cursor vermeiden, wie Sie vorschlagen. Aber sobald man über in prozeduralen Sprache überquert (wie PL / SQL), gibt es eine Reihe von Anwendungen. Zum Beispiel, wenn Sie bestimmte Zeilen und wollen abrufen möchten „to do“ etwas komplexer, als es mit ihnen zu aktualisieren.

Cursor ist auch praktisch, wenn Sie ein System proc mehrmals mit verschiedenen Eingabewerten ausgeführt werden sollen. Ich habe nicht die Absicht, zu versuchen, System Procs neu zu schreiben Set-basierte werden, so werde ich dann einen Cursor verwenden. Und Sie werden in der Regel durch eine sehr begrenzte Anzahl von Objekten. Sie können das gleiche tun mit einem bestehenden proc, dass nur ein Datensatz zu einem Zeitpunkt einsetzt, sondern von einer Performance-Ansicht, dies ist in der Regel eine schlechte Sache, wenn Sie eine Menge Datensätze durchlaufen. Diejenigen, ich werde umschreiben Set-basierte werden.

Beim Laufen Summen wie von anderen diskutiert schneller sein kann.

Wenn Sie aus der Datenbank werden per E-Mail (nicht die beste Idee, aber manchmal ist es, was Sie mit stecken), dann kann ein Cursor, den Kunden stellt nicht sicher, Kunden b E-Mail-Adresse sehen, wenn Sie beide die gleiche E-Mail senden.

Mit einem Cursor verwenden, ist in der Regel ein Zeichen dafür, dass Sie in der Datenbank tun, was sollte in der Anwendung durchgeführt werden. Wie andere gesagt haben, werden Cursor im Allgemeinen benötigt, wenn eine gespeicherte Prozedur ausgeführt Summen berechnet wird, oder wenn Sie Generieren von Code und / oder Meta-Programmierung.

Aber warum tun Sie diese Art von Arbeit in einer gespeicherten Prozedur in erster Linie? Ist das wirklich die beste Nutzung Ihrer Datenbank-Server? Ist T-SQL wirklich die richtige Sprache zu verwenden, bei der Codegenerierung?

Sicher, manchmal die Antwort „ja“ oder, was wahrscheinlicher ist, „Nein, aber es ist einfacher, auf diese Weise.“ Aus meiner Sicht übertrumpft Dinge einfach zu halten vorzeitige Optimierung an jedem Tag der Woche. Also ich benutze Cursor. Aber wenn ich glaube, ich brauche einen Cursor zu verwenden, wird das Universum mir eine Frage zu stellen, dass ich wirklich eine gute Antwort haben sollte.

Wenn eine Tabelle aus irgendeinem Grunde nicht-indiziert ist, wird ein Cursor schneller sein als andere Methoden der Iteration über einen Tisch. Ich fand diese Informationen in dieser Blog-Eintrag auf Cursor in SQL Server im letzten Jahr.

Während der Autor für „verwenden nur als letztes Mittel“ -Ansatz (wie jeder hier), hat sie einen Fall oder zwei finden, wo Cursor sowie weitere Alternativen durchführen (einschließlich der laufenden Summen wiesen darauf hin, durch Robert Rossney). Zu den weiteren interessanten Punkte, die sie macht, zeigt sie, dass Cursor effizienter innerhalb von gespeicherten Prozeduren als als Ad-hoc-Abfragen arbeiten. Der Autor hat auch eine ausgezeichnete Arbeit, darauf hinzuweisen, wenn die Leistung Probleme, die wir alle Mitarbeiter mit Cursor auftreten beginnen.

Der Blog-Eintrag enthält eigentlichen Code, damit die Leser die Abfragen selbst ausprobieren können und die Ergebnisse sehen.

Nun ja, eine Operation, bei den Cursor sind besser als Sätze, wenn eine laufende Summe und ähnliche Sachen zu berechnen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top