2011-01-08 23 views
5

Ich habe eine Tabelle in SQL Server 2008 (SP2) mit 30 Millionen Zeilen, Tabellengröße 150 GB, gibt es ein paar int Spalten und zwei nvarchar (max) Spalten: eine mit Text (von 1 -30000 Zeichen) und eines mit xml (bis zu 100000 Zeichen).Aktualisierung Tabelle dauert sehr lange

Die Tabelle enthält keine Primärschlüssel oder Indizes (es handelt sich um eine Zwischenspeichertabelle). So leite ich eine Abfrage:

UPDATE [dbo].[stage_table] 
SET [column2] = SUBSTRING([column1], 1, CHARINDEX('.', [column1])-1); 

die Abfrage ausgeführt wird für 3 Stunden (und es ist noch nicht fertig gestellt), die ich denke, ist zu lang. Ist es? Ich kann sehen, dass es eine konstante Leserate von 5MB/s und eine Schreibrate von 10MB/s zu einer .mdf-Datei gibt.

Wie kann ich herausfinden, warum die Abfrage so lange läuft? Der "Server" ist i7, 24GB RAM, SATA-Laufwerke auf RAID 10.

Aktualisiert:

Tabelle enthält eine Int-Spalte, zwei nvarchar (20) Spalten und zwei nvarchar (max) Spalten. Column1 und Columns2 in der update-Klausel oben sind nvarchar (20) Spalten. Die "großen" Spalten werden nicht aktualisiert.

Vielen Dank!

+0

Sind die Update-Spalten indiziert? – IamIC

Antwort

3

Ehrlich gesagt, das ist eine riesige Menge an Arbeit, die Sie tun (Text suchen und ersetzen auf 150 Gigabyte). Wenn die gestaffelten Daten außerhalb der Datenbank erstellt wurden, können Sie die Textoperationen dort ohne den zusätzlichen Datenbankaufwand ausführen.

+0

Danke für Ihre Antwort. Ich habe die Frage aktualisiert. Die Spalte1 und die Spalte2 sind nvarchar (20) Spalten, so dass der gesuchte Text nicht so groß ist, nur die Tabelle ist riesig. – rrejc

+0

Ich vermute, es ist immer noch wahr, dass es besser wäre, dies außerhalb der Datenbank zu tun. Der Aufwand für die Verarbeitung und Aktualisierung jeder dieser Zeilen ist sehr hoch - nicht so sehr, als ob Sie auf der gesamten Textbasis arbeiten, aber immer noch sehr viel. –

1

Sie führen eine Zeichenfolgenmanipulation auf einem Feld aus - etwas, für das SQL bekanntermaßen schlecht ist. Erwäge, eine SQL CLR-Funktion zu schreiben, die das tut, was du brauchst, und benutze das anstelle von SUBSTRING([column1], 1, CHARINDEX('.', [column1])-1).

+0

Wenn es keine Auswahlkriterien gibt, warum ist das Fehlen von Indizes wichtig? – sgmoore

+1

Ich sehe nicht, wie ein Index die Abfrage verbessern kann. Es muss nur ein vollständiger Tabellenscan sein. –

+2

Warum sollte ein Index diese UPDATE beschleunigen? Es gibt keine WHERE-Klausel. In der Tat würde für diesen UPDATE ein Index die Dinge verlangsamen (wegen der Zeit, die benötigt wird, um die Indizes zu aktualisieren). –

0

Eine praktische Möglichkeit, zu testen, ob etwas Außergewöhnliches ist, besteht darin, nur einige der Daten zu aktualisieren. Schreiben Sie eine Ansicht, in der die obersten 10.000 Zeilen angegeben werden, und führen Sie das Update für die Ansicht aus.

Wenn 10.000 Zeilen in dem, was Sie für Ihren Server "normal" erwarten, aktualisiert werden, dann würde es folgen, dass es nur "eine Menge zu aktualisierender Daten" ist.

Wenn dieses kleine Update übermäßig lange scheint, dann untersuchen Sie mehr.

Zumindest gibt dies Ihnen einen anständigen Testboden.

1

Eine praktische Möglichkeit, zu testen, ob etwas Außergewöhnliches ist, besteht darin, nur einige der Daten zu aktualisieren. Schreiben Sie eine Ansicht, in der die obersten 10.000 Zeilen angegeben werden, und führen Sie das Update für die Ansicht aus.

Wenn 10.000 Updates in dem, was Sie für Ihren Server "normal" erwarten würden, dann würde es folgen, dass es nur "eine Menge zu aktualisierender Daten" ist.

Wenn diese kleinen Updates übermäßig lang erscheinen, dann untersuchen Sie mehr.

Zumindest gibt dies Ihnen einen anständigen Testboden.

1

Hier gibt es ein paar Optionen. Aber ohne weitere Informationen darüber, was Sie mit den Daten nach diesem Update machen wollen, klingt Larry Lustigs Antwort am besten. Aber andere Optionen folgen:

  • Erstellen Sie Spalte2 als eine berechnete Spalte anstelle einer physischen Spalte.
  • Führen Sie die Berechnung, wie Sie die Daten aus der Staging-Tabelle ziehen (was auch passieren würde, wenn Sie mit dem vorherigen Kugel gehen.
  • Index Spalte2 und führen Sie dann die Updates in Teilen von 10.000 Datensätze oder so wo Spalte2 null ist. nach unten Diese die impliziten Transaktionsgröße zu halten, was wahrscheinlich ist, was zur Zeit Ihre Leistung tötet.
1

ich nicht diese Art der Verarbeitung in SQL Server getan haben, so bin ich nicht sicher, ob Der Ratschlag gilt vollständig, aber ich bin zuversichtlich genug, um Ihnen vorzuschlagen, es zu versuchen.

Was ich normalerweise in Oracle tue, ist die vollständige Vermeidung von Aktualisierungen bei der Verarbeitung aller Zeilen in einer Situation wie der von Ihnen beschriebenen (Einzelbenutzer, Batch-Ereignis).

Entweder ich migrieren die Logik von der Update-Anweisung zurück zu der Anweisung, die die Zeilen eingefügt. Oder wenn dies nicht möglich ist, erstelle ich eine neue Tabelle und lege die Aktualisierungslogik in die Auswahlliste. Zum Beispiel, statt

UPDATE [dbo].[stage_table] 
SET [column2] = SUBSTRING([column1], 1, CHARINDEX('.', [column1])-1); 

tun würde ich tun:

create table stage_table2 as 
    select column1 
     ,substring(column1, 1, charindex('.', column1)-1) as column2 
     ,column3 
     ,column4 
    from stage_table; 

drop table stage_table; 

alter table stage_table2 rename to stage_table; 
-- re-create indexes and constraints, optionally gather statistics 

ich auch dieses mit paralleler Abfrage tun könnte und NOLOGGING Option sehr wenig Redo zu generieren und nicht rückgängig gemacht wird überhaupt, die eine würde übertreffen Update-Statement mit solch einem großen Rand ist es nicht einmal lustig :) Natürlich ist dies wegen Oracle Interna, aber ich denke, es wäre möglich, es mit SQL Server replizieren. Es gibt etwas in Ihrer Beschreibung, das dies jedoch zu einem weniger effizienten Ansatz machen kann. Sie hatten einige sehr große Textspalten, die Sie in der CTAS-Anweisung "mitziehen" müssten.

Auch müssen Sie Ihre Hardware-Setup untersuchen, weil es nicht geeignet ist, mit der Menge der Daten zu arbeiten, die Sie geworfen haben. Entweder es ist etwas falsch mit der Konfiguration, oder Sie haben eine Menge anderer Aktivitäten los:

kann ich sehen, dass es konstant ist Rate von 5 MB/s Lese- und Schreibgeschwindigkeit von 10 MB/s zu. MDF-Datei.

Ich kann das auf meinen Freundinnen 2 Jahre alten Laptop schlagen. Bei einer Lesegeschwindigkeit von 5 mb/s und einer Tabelle von 150 GB würde es 8,5 Stunden dauern, um nur einmal durch die Tabelle zu scannen. Dies setzt voraus, dass die Datenbank 0% Overhead hinzufügt, was nicht der Fall ist.

Verwandte Themen