2010-09-13 8 views
7

Wir haben eine Reihe von Datenbanken, die 10 bis 100 Gigabyte Daten in einer der Tabellen speichern. Es enthält Bilddaten. Das Problem besteht darin, dass viele dieser Datenbanken nicht ordnungsgemäß erstellt wurden. Grundsätzlich ist der Primärschlüssel kein Primärschlüssel. Sie wurden mit einem eindeutigen Index für eine Spalte mit NULL-Wert erstellt. Und einige von ihnen haben einen Int als Primärschlüssel anstelle eines Bigint.Effizienter Weg, um 100 GB zu ändern Tabelle

Also haben wir langsam durch und reparieren diese Datenbanken. Sie werden auf SQL Server 2000 mit SQL Server 2008 ausgeführt, obwohl die meisten Probleme mit Primärschlüsseln auf SQL Server 2000 auftreten. Das Problem besteht darin, dass wir die Datenbank während der Konvertierung der Tabelle nicht einen ganzen Tag lang sperren möchten. Wir haben verschiedene Strategien durchgespielt:

  1. Weisen Sie SQL Server an, den Spaltentyp direkt zu ändern. Dies sperrt die Tabelle, bis sie abgeschlossen ist, und nachdem sie in vielen Fällen über Nacht verlassen wurde, war sie immer noch nicht beendet.

  2. Fügen Sie alle Bilder in einer neuen Tabelle in einem Rutsch ein. Dies wurde leichter unterbrochen, aber die gesamte Tabelle wird dabei in die Protokolldatei geschrieben.

  3. Fügen Sie 100 Zeilen gleichzeitig ein, wenn die Zeilen in der Zieltabelle nicht vorhanden sind. Der Vorteil ist, dass sie die Datenbank weiterhin verwenden können, während dies läuft (mit einem großen Leistungseinbruch) und dass sie jederzeit an beliebiger Stelle angehalten und neu gestartet werden kann und die 100 GB + Protokolldateien verhindert werden. Dies ist, was wir gerade tun, aber das Finden der obersten 100 Zeilen, die nicht existieren, wird wirklich sehr langsam, wenn die Zieltabelle größer und größer wird. UPDATE STATISTICS und DBCC INDEXDEFRAG helfen erheblich, aber beim jüngsten Versuch sind wir auf den Punkt gekommen, dass sogar 100 Bilder gleichzeitig dort nicht reagierten.

    INSERT INTO %s 
        SELECT TOP 100 Source.* 
        FROM %s AS Source WITH (NOLOCK) 
        LEFT OUTER JOIN %s AS Target WITH (NOLOCK) ON Source.DocumentID = Target.DocumentID 
        WHERE Target.DocumentID IS NULL 
        ORDER BY Source.DocumentID 
    

Also die Frage ist, gibt es eine Option, die von Massendaten in einer effizienten und fortsetzbar Weise kopieren? Es muss nicht 100% genau sein, wir können immer zurückgehen und alle Unstimmigkeiten am Ende beheben, solange es 99% der Arbeit macht.

Antwort

3

Die Verbindung ist das Problem. Tu das nicht. Durchlaufen Sie einfach Ihre aktuelle Tabelle mit einem vernünftigen Intervall und verwenden Sie den aktuellen Clustered-Index. Etwas wie:

Declare @idrange int; 
Set @idrange = 1; 

WHILE @idrange < 10000000 

INSERT INTO Destination 
    SELECT * 
    FROM Source 
    WHERE DocumentID between @idrange and @idrange + 999 
    ORDER BY Source.DocumentID 

Set @idrange = @idrange + 1000 
End 

Beachten Sie, dass für die beste Geschwindigkeit, alle Indizes entfernen (einschließlich des gruppierten Index) aus der Zieltabelle, dann die Indizes hinzufügen, sobald alle Zeilen eingefügt wurden.

EDIT: änderte das Kreisintervall eine Überlappung zu vermeiden (da zwischen den Endpunkten enthält)

Eine endgültige Klärung: der Gesamtpunkt meiner Beispielskript ist, dass Sie durch Ihre aktuellen Aufzeichnungen gehen wollen in einige vernünftige Reihenfolge, und legen Sie sie alle in der neuen Tabelle in Batches. Es gibt keinen Grund, die Zieltabelle jedes Mal erneut zu überprüfen, da Sie bereits wissen sollten, was Sie dort abgelegt haben und was noch übrig ist. Meistens macht es Sinn, den gruppierten Index zu verwenden (wenn es einen gibt), da dies bedeutet, dass er durch die physische Reihenfolge der Tabelle gehen kann, ohne Bookmark-Lookups durchzuführen. Wenn die Tabelle keinen Cluster hat, dann benutze einfach das, was am meisten Sinn macht (wahrscheinlich deine PK).

+0

Der Primärschlüssel für diese Tabelle ist nicht gruppiert. Das Konvertieren in einen gruppierten Index wäre fast so schmerzhaft wie das erneute Erstellen der Tabelle, da sie alle Daten physisch neu anordnen muss. –

+0

Es ist nach Bereichen effizienter als die Join-Methode. Ich muss sehen, wie es in der Praxis funktioniert, aber was ich gehofft hatte, war, dass es eine Möglichkeit gab, die Einfügungen auf nicht-atomare Weise auszuführen, wobei, wenn es auf halbem Wege stehenbliebe, es bereits geschehen würde Vermeiden Sie das zusätzliche Schreiben in die Protokolldatei. –

+0

@Bryce Wagner - Also, wenn es nicht auf der PK gruppiert ist, dann machen Sie einen äquivalenten Bereich oder Gruppierung auf was auch immer es ist * clustered auf. (Bitte sagen Sie mir, es hat einen Cluster, und das ist nicht nur ein HEAP) – BradC

Verwandte Themen