Was ist der beste Weg, um ein großes Dataset in eine MySQL-Datenbank (oder eine Datenbank im Allgemeinen) einzufügen?

9

Im Rahmen eines PHP-Projekts muss ich eine Zeile in eine MySQL-Datenbank einfügen. Ich bin das natürlich gewohnt, aber dafür musste in einer Abfrage in 90 Spalten eingefügt werden. Die resultierende Abfrage sieht schrecklich und monolithisch aus (insbesondere das Einfügen meiner PHP-Variablen als Werte):

INSERT INTO mytable (column1, colum2, ..., column90) 
VALUES
('value1', 'value2', ..., 'value90')

und ich mache mir Sorgen, dass ich das nicht richtig mache. Ich habe auch eine lange (langweilige) Zeit gebraucht, um alles einzutippen, und das Testen des Testcodes wird meiner Meinung nach ebenso mühsam sein.

Wie schreiben und testen Profis diese Abfragen schnell? Gibt es eine Möglichkeit, den Prozess zu beschleunigen?

Joe
quelle
2
Ich mache mir mehr Sorgen, dass die Tabelle 90 Spalten enthält als die triviale Zeit, die für die Eingabe von Spaltennamen aufgewendet wird. (Übrigens, ich ziehe alle Spalten in SQL Server gleichzeitig per Drag & Drop. Gibt es in mySQL oder PHP nicht die Möglichkeit, dasselbe zu tun? Ich würde nachsehen, ob Sie feststellen können, dass dies das Leben einfacher macht, da es keine Tippfehler gibt.)
HLGEM
1
Ich weiß, dass 90 Spalten viel sind, aber jede Spalte bezieht sich auf ein einzelnes Feld für ein PDF-Dokument, das ich ausfüllen muss, und ich sehe keinen Sinn darin, es aufzubrechen, oder wie ich das tun würde. Vielen Dank für die Informationen zu SQL Server. Ich bin mir nicht ganz sicher, was du mit Ziehen und Ablegen der Spalten meinst, aber ich werde einen Blick darauf werfen.
Joe
1
Schreiben Sie eine select-Anweisung, die alle Spalten in einer bestimmten Tabelle auflistet, und gehen Sie von dort aus.
JeffO
Jeff O: Ich habe das auch benutzt, es kann eine sehr mächtige Technik sein, wenn es richtig gemacht wird. Sie sollten dies als Antwort posten, wenn Sie ein Codebeispiel geben können!
FrustratedWithFormsDesigner

Antworten:

7

Joe, dein letzter Kommentar hat viel erklärt. Ich denke, das eigentliche Problem ist das Daten-Design. Neue Spalten können erforderlich sein, wenn sich das Dokumentformat ändert, und meiner Erfahrung nach ändern sich Dokumentformate häufig. Anstelle einer Tabelle mit 90 Spalten und einer einzelnen Zeile pro Bericht würde ich die Berichtsdaten in einer Tabelle mit vier Spalten speichern: Berichts-ID, Format-ID, Feldname, Feldwert. Jeder Bericht würde durch 90 Zeilen dargestellt, eine für jeden Feldwert im Bericht. Dies sollte Ihren Code erheblich vereinfachen.

Kevin Cline
quelle
Danke für deine Antwort. Alle Felder (außer dem Index) sind VARCHARS, das würde für mich funktionieren (und ich könnte trotzdem andere Werte konvertieren). Ich könnte jedoch viel Platz verschwenden, da ich die Größe der Spalte field_value auf den größten Wert (ungefähr 256 Zeichen lang) setzen müsste, während einige Felder nur eine Länge von 3 erfordern. Die Verwendung wäre sicherlich einfacher und ich kann verstehen, wie es zukunftssicherer wäre, als Sie beschrieben haben.
Joe
4
FWIW, die meisten Datenbanksysteme verwenden nur so viel Speicherplatz wie zum Speichern von Daten erforderlich. Wenn Sie also nur 3 Zeichen in einem VARCHAR (256) -Feld speichern, werden nur 3 Bytes benötigt, nicht 256. Ich weiß nicht viel über MySQL-Interna, aber ich wäre überrascht, wenn sie ihre Felder vollständig ausfüllen würden deklarierte Größe.
TMN
@TMN Das bedeutet der VAR in VARCHAR! Variable Länge Char. Dies ist eine Funktion (oder die Definition) des Datentyps, nicht des DB-Systems. Da ein VARCHAR eine variable Länge hat, muss die Datenbank die Länge für jeden Wert kennen, damit sie die Länge als Metadaten speichert. Das bedeutet Overhead-Speicher! Ein VARCHAR (1) verwendet also aufgrund des Overheads tatsächlich 3 Datenbytes, 3x so viel wie ein Char (1)!
Idioten
2
-1, ich bin mit dieser Antwort nicht einverstanden. In diesem Fall sind Sie mit 90 Spalten besser dran. Wenn die Entität 90 Datenpunkte hat, sollten Sie Ihre Daten rational halten.
Idioten
@TMN nur um meinen Punkt zu verdeutlichen, sagte: "Wenn Sie also nur 3 Zeichen in einem VARCHAR (256) -Feld speichern, werden nur 3 Bytes benötigt." Die Wahrheit ist, dass es 5 Bytes und nicht 3 Bytes benötigt.
Morons
7

Im Allgemeinen können Sie ein großes Dataset am schnellsten in eine SQL-Datenbank laden, indem Sie die native Bulk-Ladeschnittstelle verwenden. Soweit ich weiß, hat jede SQL-Datenbank mindestens eine.

MySQL-Dokumente: Verwenden des Bulk Loader

Wenn ich habe eine Tab- oder kommagetrennte Datei in SQL INSERT - Anweisungen zu machen, verwende ich awk die Eingabedatei zu lesen und die Ausgabedatei schreiben. Awk hat nichts Besonderes; Es ist einfach die Textverarbeitungssprache, die ich am besten kenne. Sie können dieselben Ergebnisse erzielen, indem Sie Code in Perl, Python, Ruby, Rexx, Lisp usw. schreiben.

Mike Sherrill 'Cat Recall'
quelle
2
Massenladen ist in der Tat der richtige Weg, wenn Sie eine große Anzahl von Zeilen einfügen müssen, aber in diesem Fall fügt er nur eine einzelne Zeile mit vielen Spalten ein. Das Laden in großen Mengen hilft nicht und erfordert wahrscheinlich das Schreiben von mehr Code als der einfache Ansatz.
TMN
-1, diese Antwort fehlt völlig der Punkt der Frage
Doc Brown
2

Wenn Sie die Spaltennamen problemlos in eine Excel-Tabelle einfügen können, können Sie Excel-Makros schreiben, um Code für verschiedene Abfragen und DML-Anweisungen zu erstellen. Fügen Sie dann einfach Werte in eine andere Spalte ein, und Ihre Anweisung zum Einfügen / Aktualisieren wird automatisch für Sie erstellt. Das manuelle Tippen ist eine sehr langsame Methode. Sehen Sie also nach, ob Sie mit Ihren vorhandenen Tools Tricks finden können. Viele entwicklerorientierte Texteditoren können auch Makros aufzeichnen und speichern, um sich wiederholende Jobs wie diesen viel schneller und einfacher zu machen.

FrustratedWithFormsDesigner
quelle
2

Wenn Sie eine CSV-Datei haben, können Sie die Daten mit LOAD DATA INFILE ... importieren.

Wenn Sie 'INSERT'-Abfragen verwenden müssen, wird der Vorgang durch Masseneinfügungen beschleunigt. Anstatt eine 'INSERT'-Abfrage für jede einzelne Zeile auszuführen, gruppieren Sie die Zeilen, z. B. 100, und führen Sie die Abfrage aus. Etwas wie das:

INSERT INTO theTable (col1, col2, col3,....., col89, col90) 
VALUES
(val11, val12, val13, ........, val189, val190),
(val21, val22, val23, ........, val289, val290),
.......
......
(val101, val102, val103, ........, va1089, val1090);
Srisa
quelle
2

Eine effiziente Möglichkeit, mehrspaltige Abfragedaten in MySQL DB zu schreiben, besteht darin, diese Daten in das JSON- oder YAML-Format zu konvertieren und als einzelne Einheit einzufügen. Es ändert "Schreiben Sie eine Einfügung für eine Tabelle mit 90 Spalten" in "Schreiben Sie eine Einfügung in eine Tabelle mit einer Spalte".

Bei diesem Ansatz muss nicht alles in seine Basiskomponenten zerlegt werden, und das einzelne Datum wird nur in einer Spalte gespeichert.

Noviff
quelle
@gnat: Es bietet eine alternative Lösung. Es ändert "Schreiben Sie eine Einfügung für eine Tabelle mit 90 Spalten" in "Schreiben Sie eine Einfügung in eine Tabelle mit einer Spalte". Angesichts des beschriebenen Problems ist es eine gültige Lösung. Nicht alles muss in seine Basiskomponenten zerlegt werden. Die einzige andere ähnliche Antwort schlug vor, NoSQL vollständig zu verwenden und die SQL-Datenbank vollständig zu eliminieren, was übertrieben ist. Diese Antwort besagt, dass Sie einen gemischten Ansatz verwenden können. Machen Sie nur 1 Spalte für dieses einzelne Datum. Bedenken Sie, dass die Alternative darin bestehen könnte, eine Binärspalte zu haben und das gesamte PDF zu speichern.
jmoreno
@gnat: Ich werde Noviff die Chance geben, es in seinen eigenen Worten
auszudrücken
@ gnat und jmoreno - danke für deine Kommentare. Ich mag die Klarstellung meiner Antwort durch Mücke, und ich habe die Antwort basierend auf seiner Klarstellung bearbeitet.
Noviff
0

Mit MySQL können Sie alternative Syntax für insertAnweisungen verwenden:

insert into table
        set column1 = value1
          , column2 = value2
          , column3 = value3
Kaspars Foigts
quelle
1
Ist das eigentlich schneller?
Pacerier
@ Pacerier Nein, das geht nicht schneller. Nur eine andere Syntax.
Kaspars Foigts
0

Ihr Szenario passt sehr gut zu einer NoSQL-Lösung, da sich die Attributliste jederzeit ändern kann, wenn sich das Format ändert. Haben Sie andere Optionen als MySQL evaluiert? Stöbern Sie in DynamoDB / MongoDB / Cassandra - das passt vielleicht besser.

Subu Sankara Subramanian
quelle
-1

Es gibt eine effizientere Möglichkeit, Daten mithilfe von PHP und MySQL in die Datenbank einzufügen. Wir können LOAD COMMAND verwenden, um die Daten einzufügen. Es fügt Daten bemerkenswert schnell ein.

Erstellen Sie dazu eine flache Datei (zum Beispiel habe ich eine CSV-Datei verwendet) mit Ihren Daten mithilfe der fputcsv()Funktion. Fügen Sie dann Daten mit dem Befehl LOAD ein. Syntax einige ähnlich wie unten:

LOAD DATA LOCAL INFILE "C:/downloads/local/my_data_file.csv"
INTO TABLE  my_data
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES;
Subodh
quelle
-1

Versuche Folgendes. Hat für mich gearbeitet.

Formularnamen müssen den Namen der Datenbankspalten entsprechen

Erhalten Sie die folgenden Werte:

foreach ($_GET as $formName => $value) {
    $sql = mysql_query("UPDATE table_name SET $formName = '$value' WHERE ID= $id");
}

Sie müssen zuerst eine ID vor der foreach-Schleife einfügen. Sie können die nächste ID erhalten, indem Sie Folgendes tun:

SELECT MAX(id) FROM .....

addiere 1 zu id und füge es ein.

Engel
quelle