Frage zur Eingabe-Effizienz

Frage zur Eingabe-Effizienz

am 24.06.2007 03:23:40 von Tobias Wendorff

Hallo Leute,

ich möchte ca. 2000 Zeilen aus einer CSV-Datei in eine mySQL-Datenbank
eintragen. Da ich jedoch einige Werte verändern muss, kann ich diese
nicht direkt in die Datenbank laden. Ich verwende dazu PHP.

Die 1. Spalte der Datenbank ist ein Datumsfeld (DATEFIELD), gefolgt
von verschiedenen Einzelwerten in den anderen Spalten.

Ich sehe nun zwei Möglichkeiten:

1. Ich lese das Datum und die Zeit aus der CSV-Datei, formatiere sie
nach DATETIME und schreibe sie ins 1. Feld der 1. Reihe (INSERT INTO).
Dann gehe ich die anderen Felder der CSV durch und füge jedes Mal
einen Eintrag zur 1. Reihe dazu (UPDATE). Bei 15 Feldern pro Zeile
wären es also insgesamt 15 Anfragen (1x INSERT, 14x Update).

2. Ich lese das Datum und die Zeit aus der CSV-Datei, formatiere sie
nach DATETIME und schreibe sie und alle anderen Felder in ein Array.
Danach arbeite ich das Array auf einen Schlag ab. Bei 15 Feldern
pro Zeile würde es also nur eine lange INSERT-Anfrage geben.

"Variante 1" belastet also die SQL-Datenbank ziemlich stark.
"Variante 2" zieht viel PHP-Resourcen.

Was würdet ihr verwenden?

Grüße
Tobias

Re: Frage zur Eingabe-Effizienz

am 24.06.2007 08:29:57 von Andreas Kretschmer

Andreas
--
q: why do so many people take an instant dislike to mysql?
a: it saves time (oicu in #postgresql)
Explaining the concept of referential integrity to a mysql user is like
explaining condoms to a catholic (Shadda in #postgresql)

Re: Frage zur Eingabe-Effizienz

am 24.06.2007 10:56:22 von dnoeth

Tobias Wendorff wrote:

> ich möchte ca. 2000 Zeilen aus einer CSV-Datei in eine mySQL-Datenbank
> eintragen. Da ich jedoch einige Werte verändern muss, kann ich diese
> nicht direkt in die Datenbank laden. Ich verwende dazu PHP.

Selber Schuld :-)

Wenn mangels passendem ETL-Tool das Extract-Transform-Load nicht geht,
dann nimmt man ELT (Extract-Load-Transform) mit einer Stagetable:

Lade die Daten 1:1 in eine Zwischentabelle, und mache die Änderungen im
Select-Teil eines Insert/Select in die Zieltabelle. Da sollte immer
effizienter sein als Tausende von einzelnen Inserts/Updates.

Dieter

Re: Frage zur Eingabe-Effizienz

am 24.06.2007 16:16:01 von Tobias Wendorff

Dieter Noeth wrote:
> Lade die Daten 1:1 in eine Zwischentabelle, und mache die Änderungen
> im Select-Teil eines Insert/Select in die Zieltabelle. Da sollte immer
> effizienter sein als Tausende von einzelnen Inserts/Updates.

Dazu müsst ich aber wissen, wo die Änderungen zu machen sind. Aufgrund
der schlechten Datenqualität ist das aber nicht immer vorhersagbar :-(

Re: Frage zur Eingabe-Effizienz

am 24.06.2007 16:17:28 von Tobias Wendorff

Andreas Kretschmer wrote:
> awk und daraus eine COPY-Anweisung machen.

Also im Endeffekt die CSV-Datei "offline" vorbereiten und dann
in die Datenbank kopieren? Stimmt, das klingt total logisch :-)

Re: Frage zur Eingabe-Effizienz

am 24.06.2007 16:20:53 von Claus Reibenstein

Tobias Wendorff schrieb:

> ich möchte ca. 2000 Zeilen aus einer CSV-Datei in eine mySQL-Datenbank
> eintragen.

Mehr nicht?

> 1. Ich lese das Datum und die Zeit aus der CSV-Datei, formatiere sie
> nach DATETIME und schreibe sie ins 1. Feld der 1. Reihe (INSERT INTO).
> Dann gehe ich die anderen Felder der CSV durch und füge jedes Mal
> einen Eintrag zur 1. Reihe dazu (UPDATE). Bei 15 Feldern pro Zeile
> wären es also insgesamt 15 Anfragen (1x INSERT, 14x Update).

Umständlich.

> 2. Ich lese das Datum und die Zeit aus der CSV-Datei, formatiere sie
> nach DATETIME und schreibe sie und alle anderen Felder in ein Array.
> Danach arbeite ich das Array auf einen Schlag ab. Bei 15 Feldern
> pro Zeile würde es also nur eine lange INSERT-Anfrage geben.

Schon wesentlich effektiver.

> "Variante 1" belastet also die SQL-Datenbank ziemlich stark.
> "Variante 2" zieht viel PHP-Resourcen.

So viel PHP-Ressourcen sind das nun auch wieder nicht.

> Was würdet ihr verwenden?

Veriante 3: Du liest die gesamte Datei (oder, falls das nicht geht,
zumindest größere Häppchen) auf einen Rutsch in ein Array, änderst alle
Daten wie gewünscht in diesem Array, am besten schon beim Lesen, und
schreibst sie in einem Rutsch in die Datenbank. Dann reicht ein einziges
INSERT für alle Daten (bzw. für ein Häppchen).

Gruß. Claus

Re: Frage zur Eingabe-Effizienz

am 24.06.2007 16:37:44 von Andreas Kretschmer

Andreas
--
q: why do so many people take an instant dislike to mysql?
a: it saves time (oicu in #postgresql)
Explaining the concept of referential integrity to a mysql user is like
explaining condoms to a catholic (Shadda in #postgresql)

Re: Frage zur Eingabe-Effizienz

am 24.06.2007 18:00:59 von dnoeth

Tobias Wendorff wrote:

>> Lade die Daten 1:1 in eine Zwischentabelle, und mache die Änderungen
>> im Select-Teil eines Insert/Select in die Zieltabelle. Da sollte immer
>> effizienter sein als Tausende von einzelnen Inserts/Updates.
>
> Dazu müsst ich aber wissen, wo die Änderungen zu machen sind. Aufgrund
> der schlechten Datenqualität ist das aber nicht immer vorhersagbar :-(

Und wie machst du es mit PHP, wenn du nicht weisst, was und wo du ändern
musst?

Dieter

Re: Frage zur Eingabe-Effizienz

am 26.06.2007 01:41:53 von Tobias Wendorff

Dieter Noeth wrote:
> Und wie machst du es mit PHP, wenn du nicht weisst, was und wo du
> ändern musst?

Nun, den normalen Weg, wie z.B. mit if-Abfragen oder Switches.

Re: Frage zur Eingabe-Effizienz

am 26.06.2007 08:30:48 von dnoeth

Tobias Wendorff wrote:

>> Und wie machst du es mit PHP, wenn du nicht weisst, was und wo du
>> ändern musst?
>
> Nun, den normalen Weg, wie z.B. mit if-Abfragen oder Switches.

Wenn du ein IF schreiben kannst, dann weisst du doch, wo du ändern musst
und dann kannst du im SQL CASE nehmen, z.B.
insert into target
select
case
when Spalte1 > 15 then mach_was
when andere_bedingung then mach_was_anderes
else Spalte1
end
....
from source

Dieter

Re: Frage zur Eingabe-Effizienz

am 07.07.2007 19:55:30 von Tobias Wendorff

Dieter Noeth wrote:
> Wenn du ein IF schreiben kannst, dann weisst du doch, wo du ändern
> musst und dann kannst du im SQL CASE nehmen, z.B.
> insert into target
> select
> case
> when Spalte1 > 15 then mach_was
> when andere_bedingung then mach_was_anderes
> else Spalte1
> end
> ...
> from source

SQL entwickelt sich irgendwie zu einer eigenen Programmiersprache
für mich :-)(