2016-05-17 11 views
4

den Code mitWarum bekomme ich eine hohe Fragmentierung, wenn SqlBulkCopy verwendet wird, um große Datenmengen zwischen Datenbanken zu verschieben?

Using bcp As New SqlBulkCopy(destConnection) 
    bcp.DestinationTableName = "myOutputTable" 
    bcp.BatchSize = 10000 

    bcp.WriteToServer(reader) 
End Using 

reader Wo ein im wesentlichen ein IDataReader ist, die in einer Tabelle liest, enthält, 200K Zeilen oder so.

Die Eingabetabelle sieht wie folgt aus

CREATE TABLE [dbo].[MyTable](
    [TagIndex] [SMALLINT] NOT NULL, 
    [TimeStamp] [DATETIME] NOT NULL, 
    [RawQuality] [SMALLINT] NOT NULL, 
    [ValQuality] [SMALLINT] NOT NULL, 
    [Sigma] [REAL] NULL, 
    [Corrected] [REAL] NULL, 
    [Raw] [REAL] NULL, 
    [Delta] [REAL] NULL, 
    [Mean] [REAL] NULL, 
    [ScadaTimestamp] [DATETIME] NOT NULL 
) ON [PRIMARY 

und wird von Timestamp bestellt.

Die Ausgabetabelle hat die gleiche Struktur und den folgenden Index (und ist zu Beginn des Prozesses leer).

CREATE CLUSTERED INDEX [MyOutputTable_Index] ON [dbo].[MyOutputTable] 
(
    [TimeStamp] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) 
GO 

Künstlich Drosselung des Prozesses zu einer Zeit klein (er) Datenmengen in die Ausgabetabelle auszuführen (um < 35k) in Fragmentierung von < 5% führt, und alles ist in Ordnung.

Aber wenn ich in einem größeren Brocken sage, sagen 45k, (oder lassen Sie den Prozess die ganze 200k laufen) die Fragmentierung wird 99% +.

Um genau zu sein, wenn ich 39.773 laufen lasse, bekomme ich < 5% Fragmentierung, aber ich lief in 39.774 bekomme ich 99% Fragmentierung. Und wenn ich die Seiten untersuchen, die im Index zuweisen, sehe ich folgendes mit DBCC PAGE.

FileId PageId Row Level ChildFileId ChildPageId TimeStamp (key) 
1  18937 0 1  1   18906  2015-10-22 01:37:32.497 
1  18937 1 1  1   18686  2015-10-22 01:38:12.497 
1  18937 2 1  1   18907  2015-10-22 01:38:47.497 
1  18937 3 1  1   18687  2015-10-22 01:39:27.497 
1  18937 4 1  1   18908  2015-10-22 01:40:02.497 
1  18937 5 1  1   18688  2015-10-22 01:40:42.497 
1  18937 6 1  1   18909  2015-10-22 01:41:17.497 
1  18937 7 1  1   18689  2015-10-22 01:41:57.497 
1  18937 8 1  1   18910  2015-10-22 01:42:32.497 

Mit Blick auf die ChildPageId Spalte können wir sehen, dass die Zahlen nacheinander nicht laufen. Zum Beispiel folgt auf 18906 18686, gefolgt von 18907 mit der Serie 18686, die mit der Reihe beginnend mit 18906 verschachtelt ist, was eine Fragmentierung von über 99% bewirkt.

Die Frage ist also, was bewirkt, dass der Index in größeren Datenmengen so aufgebaut wird?

Antwort

2

Es ist schwer zu sagen, ohne mehr Daten, aber ich wette, dass Ihr Timestamp ist ein gruppierter Index verursacht dies. Versuchen Sie, die Daten nach diesem Feld zu sortieren, bevor Sie sie an die Ausgabetabelle senden.

+0

Sie könnten es auch in eine Staging-Tabelle laden und dort sortieren, bevor Sie es in die reale Tabelle einfügen. –

1

Für jeden, der am Ergebnis dieses Problems interessiert ist.

Ich fand, dass die Fragmentierung durch eine variable Anzahl von Duplikaten in der Tabelle verursacht wurde.

Um zu erklären, wie der Index in NON-UNIQUE ist es möglich, und in der Tat ist der Fall, dass die TimeStamps dupliziert sind. Aber wenn die Gruppen alle die gleiche Größe haben, das heißt zum Beispiel 7 Zeilen pro Zeitstempel konsistent durch die Datei, dann wäre die Fragmentierung < 1% nach Abschluss. Aber wenn die Tabelle variabler wäre, würde die Fragmentierung schnell ansteigen. Zum Beispiel, wenn es Chunks von Daten mit 7 Zeilen pro Zeitstempel gäbe, dann wären einige mit 6, einige mit 5 usw. Fragmentierung über 99% mit diesem Interleaving, das wir sehen (wie in der Frage beschrieben).