Riesige Tabelle (9 Millionen Datensätze) im SQL Server

8

Unsere Versicherungsgesellschaft hat uns gerade einen Datenextrakt mit Leads geschickt. Es gibt 9 Millionen Zeilen. Die Zeilen bestehen aus LeadID (GUID), RawLeadXML (xml - wahrscheinlich maximal 3-4 KB) und einer LeadStatusID (int).

Ich habe zuerst versucht, eine Ganzzahl für die automatische Nummerierung hinzuzufügen und sie zum Primärschlüssel dieser Tabelle zu machen. Nun, es hat das Feld hinzugefügt, konnte es aber nicht zum Primärschlüssel machen (Im Pufferpool ist nicht genügend Speicher verfügbar.)

Was ich tun muss, ist, jeden Datensatz einzeln zu nehmen und das XML zu holen, es in ein XmlDocument-Objekt in .Net einzutragen, alle gewünschten Felder (Vorname, Nachname usw.) auszublenden und zu speichern analysierte Informationen in eine andere Tabelle.

Ich kann diese Anweisung nicht einmal ausführen: wähle * aus Leads mit der ID zwischen 1 und 1000

Wenn ich nur 1000 Datensätze gleichzeitig wähle (Top 1000 * aus Leads auswählen), funktioniert das, aber wie würde ich dann die nächsten 1000 Datensätze ohne irgendeinen Referenzpunkt auswählen?

Mein Rechner hat 4 Prozessoren (2,53 Ghz) und 12 GB RAM. Es ist kein Server, aber es ist eine bullige Maschine. Ich weiß nicht, was ich als nächstes versuchen soll, ehrlich.

BEARBEITEN : Ich habe vergessen, dass die ursprüngliche Datei tatsächlich eine MDF-Datei (und die zugehörige LDF-Datei) war, also habe ich sie in SQL Server angefügt.

BEARBEITEN 2 : Ich habe versagt und gesagt, dass die RawLeadXML-Spalte XML ist - das ist es nicht, es ist nur nvarchar (max). Ich wusste ehrlich gesagt nicht, dass es einen XML-Datentyp gab.

EDIT 3 : Ich kann nicht einmal eine delete-Anweisung für diese Tabelle ausgeben: "delete from leads where leadid = '100a7927-5311-4f12-8fe3-95c079d32dd4'" explodiert mit:

%Vor%

Ich habe keine Ahnung, was ich als nächstes tun soll. Wie zur Hölle ist das überhaupt ein Problem? Es gibt Tausende von Datenbanken in der Welt mit mehr Aufzeichnungen als ich habe.

EDIT 4 : Falls es jemanden interessiert, hat keine der folgenden Lösungen funktioniert. Ich bin sicher, dass dies eine Einschränkung meiner Maschine ist, und definitiv keine Verurteilung der feinen Antworten, die ich unten erhielt. Momentan übertrage ich die gezippte DB (2.6 GB) auf unsere Server in Rackspace, und dann werde ich versuchen, einen Index auf dieser Hardware hinzuzufügen, hoffentlich ohne unsere Produktionsserver herunterzufahren. Sobald der Index hinzugefügt ist, hoffe ich, dass ich die db komprimieren und auf meinen lokalen Rechner zurückbringen kann, und dann tatsächlich etwas damit machen kann.

EDIT 5 : Meine Maschine war buchstäblich nicht in der Lage, einen Tisch dieser Größe zu bearbeiten. Meine Maschine hat 12 GB RAM, 64 Bit Windows 7 Professional, einen Quad-Core-Prozessor mit 2,53 GHz, SSD-Laufwerk, etc. Es ist ziemlich bullig für eine Entwicklungsmaschine. Und es konnte damit nicht umgehen.

Also habe ich die DB auf unseren Server in Rackspace in London verlegt. 48 GB oder Speicher in diesem, und es war in der Lage, den Index, den ich brauchte, hinzuzufügen. Selbst danach war meine Maschine hier nicht in der Lage, alles Nützliche damit zu tun, also habe ich ein .Net-Programm geschrieben, das in London läuft, um die Datensätze 1000 gleichzeitig zu veröffentlichen, sie in einen anderen Tisch zu parsen und dann Markieren Sie die ursprünglichen Datensätze als bearbeitet.

Sobald ich das tue, werde ich die DB in London verlassen müssen, weil ich bezweifle, dass ich vor Ort nennenswerte Berichte gegen diese Monstrosität schreiben könnte. Das macht Entwicklung Spaß.

Zusammenfassung : Ich glaube, dass es keinen guten Weg gibt, einen so großen Datensatz zu verarbeiten, ohne Server-Klasse-Hardware mit mindestens 48 GB RAM zu verwenden (in meinem Fall).

    
Matt Dawdy 26.04.2011, 18:10
quelle

9 Antworten

4

9 Millionen Zeilen sind nicht so groß, Sie haben wahrscheinlich keinen Index für die LeadId-Spalte. Zuerst erstellen Sie eine, obwohl es einige Zeit dauern wird (muss nicht eindeutig oder Primärschlüssel sein). Dann benutze ein "SELECT 1000 LeadId, RawXML ORDER BY LeadId" für die erste Abfrage. Letzten LeadId-Wert (MaxLeadId) aufzeichnen, verwenden "SELECT TOP 1000 LeadId, RawXML mit LeadId & MaxLeadId ORDER BY LeadId" und so weiter ...

    
Volkan Ceylan 26.04.2011, 18:48
quelle
9

Fehler 802 bedeutet nicht zu wenig Speicher im klassischen Sinne von zu wenig Speicher für eine Zuweisung (das würde Fehler 701 ). Fehler 802 zeigt tatsächlich an, dass der Pufferpool nicht wachsen kann, was aus verschiedenen Gründen auftreten kann :

  • max server memory Einstellung verhindert explizit Pufferpoolwachstum, überprüfen Sie Ihre Servereinstellung.
  • x86 virtuelles Adressraumlimit ist erreicht und AWE ist nicht aktiviert . Überprüfen Sie, ob Sie eine x86 (32 Bit) -Instanz haben, und wenn ja, prüfen Sie, ob all die Bedingungen für die Aktivierung von AWE erfüllen.

Wenn Sie das Problem immer noch nicht gefunden haben, lesen Sie So verwenden Sie den Befehl DBCC MEMORYSTATUS, um die Speichernutzung zu überwachen SQL Server 2005 (der Artikel gilt gleichermaßen für SQL Server 2008 und 2008 R2) und befolgen Sie die Richtlinien, um zu verstehen, wer / was Ihren Speicher verbraucht.

    
Remus Rusanu 27.04.2011 04:16
quelle
3

Das Hinzufügen einer Spalte ist keine Option, da das Hinzufügen einer Auto-ID auch nicht funktioniert hat. Sie möchten die geänderten / bereinigten Daten in einer neuen Tabelle speichern. Diese Tabelle hat möglicherweise eine Auto-ID und separate Spalten für die Daten, die Sie aus dem Xml extrahieren.

Nach dem Einfügen von Daten in diese Tabelle können Sie die ursprünglichen Zeilen aus der Quellentabelle löschen. Oder machen Sie eine SELECT-Anweisung, die Zeilen mit einer GUID ausschließt, die sich bereits in der neuen Tabelle befindet.

Da die Zeilen Ihrer Quellentabelle keine Abhängigkeit oder bestimmte Reihenfolge haben, ist die Reihenfolge, in der Sie Ihre Zeilen auswählen / verarbeiten, nicht wichtig.

Basierend auf dem Kommentar ein Vorschlag für eine SQL-Anweisung:

%Vor%

Ich habe die Anzahl der Datensätze auf 100 gesetzt. Das sollte Ihre Speicherbelegung ersparen.

    
Jacco 26.04.2011 18:42
quelle
1

Haben Sie eine Festplatte übrig? Vielleicht erstellen Sie die gleiche Tabellenstruktur in einem "TableAux", aber mit einer Auto-numerischen ID und machen dann eine Einfügung aus der Tabelle ...

Importieren Sie aus einer einfachen Datei in Ihren TableAux (Exportieren zuerst, wenn es keine flache Datei ist), ist eine andere Möglichkeit.

Um eine ID für Ihre Register zu erhalten, müssen Sie mit ihnen arbeiten.

    
apacay 26.04.2011 18:24
quelle
1

Schauen Sie sich das an, indem Sie row_number () und ranks.

ausführen

Schauen Sie sich diesen Thread an . Es hat die grundlegenden Konzepte, um Sie zu beginnen.

    
clamchoda 26.04.2011 18:36
quelle
1

Was ist mit

?
  • Wählen Sie die erste Zeile (oben 1) der Tabelle, speichern Sie die LeadID in einer Var.
  • Laden Sie den Wert der XML-Spalte in das XML-Dokument (.NET)
  • Zielen Sie die Knoten an, die Sie mit xpath
  • benötigen
  • fügen Sie diese Werte in einen neuen Datensatz ein
  • Löschen Sie den Datensatz aus der Tabelle "main" mit der leadid (oder markieren Sie "done")
  • commit
  • Schritt 1 noch einmal
Ivo 26.04.2011 18:25
quelle
0

Wenn dies eine flache Datei ist, könnten Sie vielleicht die ersten 1000 Zeilen erhalten, sie laden und dann zurückgehen und die Zeilen aus der Datei entfernen, die auf der GUID basiert, und dann wiederholen? (Erstellen Sie zuerst eine Sicherungskopie der Datei.)

Sie könnten auch versuchen, diese Datei über ein Integration Services-Paket zu laden, das in der Lage sein sollte, den Speicherort des Imports zu verfolgen und sie in Stapel zu verarbeiten und innerhalb Ihrer Speicherbeschränkungen zu halten.

    
artofsql 26.04.2011 18:18
quelle
0

In welchem ​​Format erhalten Sie den Extrakt ursprünglich? Wenn es ein csv oder ein solches ist, und Sie interessieren sich nicht für die anderen Informationen in diesem XML-Fragment, würde ich SSIS verwenden und diese Zwischentabelle vollständig überspringen. Der native XML-Typ ist mit einem gewissen Mehraufwand verbunden, den Sie nicht aufwenden müssen, wenn Sie nur versuchen, einige XML-Dateien einmal zu vernichten und dann zu verwerfen.

Andernfalls sollten Sie XML-Pfadanweisungen direkt in einer SQL-Abfrage verwenden können, um die Daten von einer Tabelle in eine andere zu übertragen. Wenn Sie versuchen, eine neue PK vom Designer hinzuzufügen, kann dies an einem großen Tisch fehlschlagen. Sie müssen die Änderungen per Skript durchführen und sie manuell ausführen und sie möglicherweise optimieren, um die Effizienz zu erhöhen. Letztendlich sind 9m-Reihen nach heutigen Maßstäben nicht so riesig, aber man muss die Dinge mehr durchdenken als mit 9k.

    
superstator 26.04.2011 18:34
quelle
0

Wie wäre es mit dem Extrahieren der Daten in eine Textdatei direkt aus der Access DB - dann können Sie es einfach in das RDBM Ihrer Wahl mit einem Masseneinsatz importieren.

Der Zugriff auf DBs über Link-Tabellen in MSSQL ist nicht ideal. Hier verwenden wir einen schreibgeschützten, nur Vorwärts-Recordset-Cursor, um nacheinander durch die Zeilen zu gehen.

Dies ist VBScript, also wird es nicht das schnellste sein, aber es sollte funktionieren. Sie müssen die XML-Extraktionsroutine für Ihr Schema anpassen.

%Vor%     
Adrian 04.05.2011 16:42
quelle

Tags und Links