Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie erfasse ich die in SqlBulkCopy übergebenen Daten mit dem Sql Profiler?

Erfassen von Ereignisinformationen für Masseneinfügungsvorgänge ( BCP.EXE , SqlBulkCopy , und ich nehme BULK INSERT an , und OPENROWSET(BULK... ) ist möglich, aber Sie können die einzelnen Zeilen und Spalten nicht sehen.

Masseneinfügungsvorgänge werden als einzelne DML-Anweisung (also eine pro Stapel, und standardmäßig werden alle Zeilen in einem einzigen Stapel ausgeführt) angezeigt:

INSERT BULK <destination_table_name> (
      <column1_name> <column1_datatype> [ COLLATE <column1_collation> ], ...
      ) [ WITH (<1 or more hints>) ]

<hints> := KEEP_NULLS, TABLOCK, ORDER(...), ROWS_PER_BATCH=, etc

Die vollständige Liste der "Hinweise" finden Sie auf der MSDN-Seite für BCP Dienstprogramm . Bitte beachten Sie, dass SqlBulkCopy nur eine Teilmenge dieser Hinweise unterstützt (z. B. KEEP_NULLS , TABLOCK , und ein paar andere), aber nicht unterstützt ORDER(...) oder ROWS_PER_BATCH= (was eigentlich ziemlich unglücklich ist, da ORDER() Hinweis wird benötigt, um eine Sortierung zu vermeiden, die in tempdb stattfindet, damit die Operation minimal protokolliert werden kann (vorausgesetzt, die anderen Bedingungen für eine solche Operation wurden ebenfalls erfüllt).

Um diese Anweisung anzuzeigen, müssen Sie eines der folgenden Ereignisse in SQL Server Profiler erfassen:

Sie sollten auch mindestens die folgenden Spalten auswählen (in SQL Server Profiler):

Und da ein Benutzer keine INSERT BULK senden kann -Anweisung direkt, können Sie wahrscheinlich in den Spaltenfiltern danach filtern, wenn Sie nur diese Ereignisse und sonst nichts sehen möchten.

Wenn Sie die offizielle Benachrichtigung sehen möchten, dass ein BULK INSERT Operation beginnt und/oder endet, müssen Sie das folgende Ereignis erfassen:

und fügen Sie dann die folgenden Profiler-Spalten hinzu:

Für ObjectName Sie erhalten immer Ereignisse, die "BULK INSERT" anzeigen, und ob dies beginnt oder endet, wird durch den Wert in EventSubClass bestimmt , was entweder "0 - Begin" oder "1 - Commit" ist (und ich nehme an, wenn es fehlschlägt, sollten Sie "2 - Rollback" sehen).

Wenn die ORDER() hint wurde nicht angegeben (und wieder kann es nicht angegeben werden, wenn SqlBulkCopy verwendet wird ), dann erhalten Sie auch ein "SQLTransaction"-Ereignis, das "sort_init" im ObjectName anzeigt Säule. Dieses Ereignis hat auch die Ereignisse „0 – Begin“ und „1 – Commit“ (wie in EventSubClass gezeigt). Spalte).

Schließlich können Sie, obwohl Sie die spezifischen Zeilen nicht sehen können, immer noch Vorgänge für das Transaktionsprotokoll sehen (z. B. Zeile einfügen, IAM-Zeile ändern, PFS-Zeile ändern usw.), wenn Sie das folgende Ereignis erfassen:

und fügen Sie die folgende Profiler-Spalte hinzu:

Die interessantesten Informationen befinden sich in der EventSubClass Spalte, aber leider sind es nur ID-Werte und ich konnte keine Übersetzung dieser Werte in der MSDN-Dokumentation finden. Allerdings habe ich den folgenden Blogbeitrag von Jonathan Kehayias gefunden:Using Extended Events in SQL Server Denali CTP1 to Map out the TransactionLog SQL Trace Event EventSubClass-Werte .

@RBarryYoung wies darauf hin, dass EventSubClass-Werte und -Namen in sys.trace_subclass_values zu finden sind Katalogansicht, aber die Abfrage dieser Ansicht zeigt, dass sie keine Zeilen für das TransactionLog enthält Ereignis:

SELECT * FROM sys.trace_categories -- 12 = Transactions
SELECT * FROM sys.trace_events WHERE category_id = 12 -- 54 = TransactionLog
SELECT * FROM sys.trace_subclass_values WHERE trace_event_id = 54 -- nothing :(

Bitte beachten Sie, dass die SqlBulkCopy.BatchSize -Eigenschaft entspricht dem Setzen von -b Option für BCP.EXE , eine Betriebseinstellung, die steuert, wie jeder Befehl die Zeilen in Sätze aufteilt. Dies ist nicht dasselbe wie ROWS_PER_BATCH= hint, der nicht physisch steuert, wie die Zeilen in Sätze aufgeteilt werden, sondern es SQL Server stattdessen ermöglicht, besser zu planen, wie Seiten zugewiesen werden, und reduziert daher die Anzahl der Einträge im Transaktionsprotokoll (manchmal um einiges). Trotzdem haben meine Tests Folgendes gezeigt:

  • Angabe von -b für BCP.EXE hat ROWS_PER_BATCH= gesetzt Hinweis auf denselben Wert.
  • Angabe von SqlBulkCopy.BatchSize Eigentum nicht setzen Sie ROWS_PER_BATCH= Hinweis, ABER, der Vorteil der reduzierten Transaktionsprotokollaktivität war irgendwie definitiv da (Magie?). Die Tatsache, dass der Nettoeffekt immer noch den Nutzen bringen soll, ist der Grund, warum ich es nicht oben erwähnt habe, als ich sagte, dass es bedauerlich war, dass die ORDER() Hinweis wurde von SqlBulkCopy nicht unterstützt .