2012-04-10 8 views
1

Ich muss regelmäßig einen Großteil der Daten in eine MySQL-Datenbank aus CSV-Dateien hochladen. Ich habe dies getan, indem ich einfach LOAD DATA INFILE aus Bash-Skripten ausgeführt habe. Jetzt sollen die Daten jedoch auf mehrere Tabellen verteilt werden und Beziehungen beibehalten werden. Was sind allgemeine Strategien in solchen Fällen?Bulk-Einfügung von MySQL bezogenen Tabellen aus Bash

Nehmen wir eine anfänglich einfache Aufgabe an: Relation eins-zu-viele, zwei Tabellen.

Ich halte so etwas wie:

  1. für Tisch maximal identyfier bekommt 1
  2. manuell Identifikatoren in dem CSV-Datei
  3. Splitting die Datei mit zwei Zieltabellen im Auge
  4. Anwendung beiden Tabellen einfügen

Ist es eine optimale Lösung? (Im wirklichen Fall zum Beispiel werde ich viele n-zu-viele Beziehungen haben, die auf diese Weise aktualisiert werden.)

Kann ich die Tabelle 1 von der Ebene der Bash für die Dauer des gesamten Prozesses sperren ? Oder muss ich ein intermediäres Werkzeug wie Perl oder Python verwenden, um alle Dinge in einer Sitzung zu behalten?

+0

Ausgezeichnete erste Post! Ihre Antwort hängt davon ab, ob Sie ein Immon (ite) oder ein Kimball (ite) sind, Kimballs Data Warehouse Toolkit (Buch) (http://www.amazon.com/The-Data-Warehouse-Toolkit-Dimensional/dp/). 0471200247/ref = sr_1_1? S = Bücher & ie = UTF8 & qid = 1334075383 & sr = 1-1) argumentiert, dass die künstlichen Schlüssel vom System erzeugt werden sollen. Oder versuche einen alternativen Ansatz, der für mich gut funktioniert hat. Behalten Sie eine Reihe separater "Eingabe" -Tabellen, importieren Sie die aktuelle Datei in die leere Eingabetabelle und führen Sie dann die gespeicherte Prozedur aus, um sie in Haupttabellen zusammenzuführen. Viel Glück. – shellter

+1

Verwenden Sie awk, um die Daten vorzuverarbeiten/aufzuteilen und nur Daten in die geteilten Dateien zu laden. Wenn Sie mehr Details wünschen, müssen Sie selbst etwas bereitstellen. – Kevin

Antwort

0

Es gibt verschiedene widersprüchliche Anforderungen in Ihrer Frage ausgedrückt. Diese Antwort konzentriert sich auf den Aspekt "keep lock".

Um eine Tabellensperre für den gesamten Vorgang aufrecht zu erhalten, müssen Sie eine einzelne Verbindung zum SQL Server unterhalten. Eine Möglichkeit wäre, alles als mehrzeilige Eingabe mit mehreren Befehlen an einen einzigen Aufruf des mysql-Befehlszeilenclients zu übergeben. Im Grunde wie folgt aus:

{ echo "LOCK TABLES Table1 WRITE" 
    for i in "${infiles[@]}"; do 
    echo "LOAD DATA LOCAL INFILE '${i}'" 
    done 
} | mysql 

, dass so lange funktionieren würde, wie Sie alle erforderlichen Anweisungen ohne Fragen aus der Datenbank (zB maximaler Identifier) ​​fragen erzeugen können, während die Sperre gehalten wird.

Um Lesevorgänge (zB nach einem maximalen Wert) und Schreiboperationen (wie das Laden von Inhalten einiger Dateien) zu mischen, wird eine bidirektionale Kommunikation mit dem Server benötigt. Das durch bash zu erreichen ist sehr schwierig, daher würde ich davon abraten. Auch wenn Sie keine Fragen stellen müssen, ist die unidirektionale Verbindung durch eine Bash-Pipe eine Gefahrenquelle: Wenn auf der mysql-Seite etwas schief geht, merkt bash nichts und gibt trotzdem den nächsten Befehl aus. Sie könnten am Ende inkonsistente Daten übergeben.

Aus diesen Gründen würde ich eher eine Skriptsprache vorschlagen, für die mysql-Bindungen verfügbar sind, wie die von Ihnen erwähnten Perl- oder Pyhon-Optionen.Lesen CVS-Dateien in diesen Sprachen ist einfach, so dass Sie alle folgenden in einem einzigen Skript tun könnte:

  1. Sperre Tabellen
  2. Starttransaktion
  3. Eingang lesen csv-Dateien
  4. Fragen wie max id
  5. einstellen Eingangsdaten Tabellenlayout
  6. einfügen von Daten in Tabellen
  7. , wenn keine Fehler aufgetreten übereinstimmen, Commit-Transaktion
Verwandte Themen