Ich habe einen Prozess, der eine Reihe von Datensätzen (1000) erfasst und verarbeitet. Wenn ich fertig bin, muss ich eine große Anzahl von Datensätzen als verarbeitet markieren. Ich kann dies mit einer großen Liste von IDs anzeigen. Ich versuche, das Muster "Aktualisierungen in einer Schleife" zu vermeiden, daher möchte ich einen effizienteren Weg finden, um diese IDs in einen gespeicherten MS SQL Server 2008-Prozess zu senden.
Vorschlag Nr. 1 - Tabellenwerte. Ich kann einen Tabellentyp mit nur einem ID-Feld definieren und eine Tabelle mit IDs zum Aktualisieren senden.
Angebot Nr. 2 - XML-Parameter (varchar) mit OPENXML () im Proc-Body.
Vorschlag Nr. 3 - Listenanalyse. Ich möchte dies nach Möglichkeit lieber vermeiden, da es unhandlich und fehleranfällig erscheint.
Irgendeine Präferenz unter diesen oder irgendwelche Ideen, die ich vermisst habe?
quelle
Antworten:
Die besten Artikel zu diesem Thema stammen von Erland Sommarskog:
Er deckt alle Möglichkeiten ab und erklärt ziemlich gut.
Entschuldigen Sie die Kürze der Antwort, aber Erlands Artikel über Arrays ist wie Joe Celkos Bücher über Bäume und andere SQL-Leckerbissen :)
quelle
Auf StackOverflow gibt es eine große Diskussion darüber , die viele Ansätze abdeckt. Für SQL Server 2008+ bevorzuge ich die Verwendung tabellenwertiger Parameter . Dies ist im Wesentlichen die Lösung für Ihr Problem mit SQL Server - die Übergabe einer Werteliste an eine gespeicherte Prozedur.
Die Vorteile dieses Ansatzes sind:
Beachten Sie jedoch Folgendes : Wenn Sie eine gespeicherte Prozedur aufrufen, die TVPs über ADO.NET oder ODBC verwendet, und sich die Aktivität mit SQL Server Profiler ansehen, werden Sie feststellen, dass SQL Server mehrere
INSERT
Anweisungen zum Laden des TVP empfängt , eine für jede Zeile im TVP , gefolgt vom Aufruf der Prozedur. Dies ist beabsichtigt . Dieser Stapel vonINSERT
s muss jedes Mal kompiliert werden, wenn die Prozedur aufgerufen wird, und stellt einen kleinen Overhead dar. Doch selbst mit diesem Kopf, TVPs noch wegblasen andere Ansätze in Bezug auf Leistung und Benutzerfreundlichkeit für die meisten Anwendungsfälle.Wenn Sie mehr erfahren möchten, hat Erland Sommarskog die volle dünn wie Tabellenwertparametern arbeiten und mehrere Beispiele.
Hier ist ein weiteres Beispiel, das ich zusammengestellt habe:
quelle
CREATE TYPE
Anweisung am Anfang erfolgreich ausgeführt? Welche Version von SQL Server verwenden Sie?@customer_list
nicht@param1
. Das Beispiel zeigt einfach, dass Sie verschiedene Parametertypen mischen können.Das gesamte Thema wird in dem endgültigen Artikel von Erland Sommarskog behandelt: "Arrays und Liste in SQL Server" . Wählen Sie die gewünschte Version aus.
Zusammenfassung, für Pre- SQL Server 2008, wo TVPs den Rest übertrumpfen
Der Artikel ist auf jeden Fall eine Lektüre wert, um andere Techniken und Denkweisen kennenzulernen.
Bearbeiten: späte Antwort für große Listen an anderer Stelle: Übergeben von Array-Parametern an eine gespeicherte Prozedur
quelle
Ich weiß, dass ich zu spät zu dieser Party komme, aber ich hatte in der Vergangenheit ein derartiges Problem: Ich musste bis zu 100.000 Bigint-Nummern senden und habe einige Benchmarks durchgeführt. Am Ende haben wir sie im Binärformat als Bild gesendet - das war für bis zu 100.000 Zahlen schneller als alles andere.
Hier ist mein alter Code (SQL Server 2005):
Der folgende Code packt ganze Zahlen in einen binären Blob. Ich kehre die Reihenfolge der Bytes hier um:
quelle
Ich bin hin- und hergerissen, ob ich Sie auf SO verweise oder hier beantworte, denn dies ist fast eine Programmierfrage. Aber da ich schon eine Lösung habe, die ich benutze ... werde ich das posten;)
Die Art und Weise, wie dies funktioniert, besteht darin, dass Sie eine durch Kommas getrennte Zeichenfolge (einfache Aufteilung, keine CSV-Aufteilungen) in die gespeicherte Prozedur als varchar (4000) einspeisen und diese Liste dann in diese Funktion einspeisen und eine handliche Tabelle zurückgeben. eine Tabelle nur varchars.
Auf diese Weise können Sie nur die Werte der zu verarbeitenden IDs senden und an dieser Stelle einen einfachen Join ausführen.
Alternativ können Sie mit einer CLR-Datentabelle etwas anfangen und dies einspeisen, aber das ist ein bisschen mehr Aufwand für die Unterstützung, und jeder versteht CSV-Listen.
quelle
Ich erhalte regelmäßig Sätze von 1000 Zeilen und 10000 Zeilen, die von unserer Anwendung gesendet wurden, um von verschiedenen gespeicherten SQL Server-Prozeduren verarbeitet zu werden.
Um die Leistungsanforderungen zu erfüllen, verwenden wir TVPs. Sie müssen jedoch eine eigene Zusammenfassung des dbDataReader implementieren, um einige Leistungsprobleme im Standardverarbeitungsmodus zu beheben. Ich werde nicht auf die Fragen eingehen, da sie für diese Anfrage nicht in Frage kommen.
Ich habe die XML-Verarbeitung nicht in Betracht gezogen, da ich keine XML-Implementierung gefunden habe, die mit mehr als 10.000 "Zeilen" performant bleibt.
Die Listenverarbeitung kann durch die Verarbeitung von eindimensionalen und zweidimensionalen Tally-Tabellen (Zahlen) erfolgen. Wir haben diese erfolgreich in verschiedenen Bereichen eingesetzt, aber gut verwaltete TVPs sind leistungsfähiger, wenn es mehr als ein paar hundert "Zeilen" gibt.
Wie bei allen Entscheidungen in Bezug auf die SQL Server-Verarbeitung müssen Sie Ihre Auswahl basierend auf dem Verwendungsmodell treffen.
quelle
Endlich hatte ich die Möglichkeit, einige TableValuedParameters zu erstellen, und sie funktionieren hervorragend. Daher füge ich einen ganzen Haufen Code ein, der zeigt, wie ich sie verwende. Ein Beispiel aus einem Teil meines aktuellen Codes ist: (Anmerkung: Wir verwenden ADO .NETZ)
Beachten Sie auch: Ich schreibe Code für einen Dienst und habe viele vordefinierte Codebits in der anderen Klasse, aber ich schreibe dies als Konsolen-App, damit ich es debuggen kann die Konsolen-App. Entschuldigen Sie meinen Codierungsstil (wie fest codierte Verbindungszeichenfolgen), da er sozusagen "eine zum Wegwerfen" war. Ich wollte zeigen, wie ich a verwende
List<customObject>
und es einfach als Tabelle in die Datenbank schiebe, die ich in der gespeicherten Prozedur verwenden kann. C # - und TSQL-Code unten:Außerdem werde ich meinen Codierungsstil konstruktiv kritisieren, wenn Sie das zu bieten haben (für alle Leser, die auf diese Frage stoßen), aber bitte bleiben Sie konstruktiv;) ... Wenn Sie mich wirklich wollen, finden Sie mich hier im Chatroom . Hoffentlich kann man mit diesem Codeblock sehen, wie sie das verwenden können,
List<Current>
wie ich es als Tabelle in der Datenbank undList<T>
in ihrer App definiert habe.quelle
Ich würde entweder mit Vorschlag Nr. 1 gehen oder alternativ eine Arbeitstabelle erstellen, die nur verarbeitete IDs enthält. Fügen Sie während der Verarbeitung etwas in diese Tabelle ein und rufen Sie dann, wenn Sie fertig sind, ein Verfahren wie das folgende auf:
Sie werden viele Einfügungen machen, aber sie werden an einem kleinen Tisch sein, also sollte es schnell gehen. Sie können Ihre Beilagen auch mit ADO.net oder einem anderen von Ihnen verwendeten Datenadapter stapeln.
quelle
Der Fragentitel enthält die Aufgabe, Daten aus einer Anwendung in die gespeicherte Prozedur zu übertragen. Dieser Teil wird vom Fragenkörper ausgeschlossen, aber lassen Sie mich auch versuchen, dies zu beantworten.
Im Kontext von sql-server-2008, wie in den Tags angegeben, gibt es einen weiteren großartigen Artikel von E. Sommarskog über Arrays und Listen in SQL Server 2008 . Übrigens habe ich es in dem Artikel gefunden, auf den Marian in seiner Antwort verwiesen hat.
Anstatt nur den Link anzugeben, zitiere ich die Inhaltsliste:
Über die dort genannten Techniken hinaus habe ich das Gefühl, dass Bulkcopy und Bulk Insert in einigen Fällen eine Erwähnung verdienen, um den allgemeinen Fall zu erfassen.
quelle
Für MS SQL 2016 neueste Version
Mit MS SQL 2016 führen sie eine neue Funktion ein: SPLIT_STRING () , um mehrere Werte zu analysieren.
Dies kann Ihr Problem leicht lösen.
Für MS SQL ältere Version
Wenn Sie eine ältere Version verwenden, gehen Sie wie folgt vor:
Machen Sie zuerst eine Funktion:
Übergeben Sie anschließend einfach Ihre Zeichenfolge mit Trennzeichen an diese Funktion.
Ich hoffe das ist hilfreich für dich. :-)
quelle
Verwenden Sie dies, um "Typentabelle erstellen" zu erstellen. einfaches Beispiel für den Benutzer
quelle