Autor Beitrag
CodingForBeer
Hält's aus hier
Beiträge: 7



BeitragVerfasst: Di 23.09.14 11:42 
Hallöle,

heute beschäftige ich mich mit dem INSERT INTO und UPDATE auf eine Datenbanktabelle.

Dabei habe ich festgestellt, dass ein INSERT INTO von 10.000 Datensätzen (mit 11 Spalten)
ca. 24 Sekunden dauert, während ein Update aller Datensätze 36 Minuten dauert.

Krasser Unterschied würde ich mal sagen. :shock:

Mein Problem beim INSERT INTO ist, dass sich die Anzahl der Spalten ändern kann.
Mit einer Schleife hole ich mir die Anzahl und Namen der Spalten, kann diese
aber ja nicht dynamisch in den INSERT INTO Query einbauen.

Deswegen habe ich das mit einer UPDATE-Anweisung umgesetzt.
Es wird also vorher die Tabelle mit den entsprechenden Spalten erzeugt.
Auch die Anzahl an Datensätzen ist dann schon bekannt.
Zusätzlich erstelle ich am Anfang die Spalte ID, die die Datensätze durchnummeriert.
Die anderen Spalten (z. B. Spalte 1 bis 11) sind leer

Die Tabelle sieht also wie folgt aus:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
+-------+----------+-----+-----------+
| ID    | Spalte 1 | ... | Spalte 11 |
+-------+----------+-----+-----------+
1     | NULL     | ... | NULL      |
+-------+----------+-----+-----------+
| ...   | ...      | ... | ...       |
+-------+----------+-----+-----------+
10000 | NULL     | ... | NULL      |
+-------+----------+-----+-----------+

Mit einer Schleife führe ich den UPDATE Query aus.
ausblenden C#-Quelltext
1:
SqlCommand WORT = new SqlCommand("UPDATE " + file[c] + " SET " + value[j] + " = '" + va[j] + "' WHERE ID = " + durchgang, con);					

file[c] enthält den Tabellennamen
value[j] enthält den entsprechenden Spaltennamen
va[j] enthält den Wert, der eingetragen werden soll
Damit das in der korrekten Zeile passiert, greife ich auf die ID zu.

Die Variante mit dem UPDATE funktioniert fehlerfrei, allerdings dauert das sehr lange.

Welche Möglichkeiten gibt es, um den UPDATE Query zu beschleunigen?

Ich habe schon etwas über INDEX gelesen, verstehe das aber so, dass es eher bei SELECT Anweisungen
greift. Die Tabelle hat keinen von mir vergebenen INDEX. Die Spalte Dummy ist PK.

Mit einem SqlBulkCopy habe ich es auch schon versucht, bekomme ab einer gewissen Größe
allerdings eine OutOfMemory Exception. ;-)

Danke und Gruß
CfB

Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 23.09.14 12:56 
Zitat:
Ich habe schon etwas über INDEX gelesen, verstehe das aber so, dass es eher bei SELECT Anweisungen
greift. Die Tabelle hat keinen von mir vergebenen INDEX. Die Spalte Dummy ist PK.


Der Index hilft um Datensätze zu finden. Und zum Updaten eines Datensatzes muß man den erst in der Tabelle finden.
Zum finden der Daten wird die Where Klausel benutzt (egal ob Select, Update oder Delete). Die Spalten die in der Where Klausel benutzt werden sollten also für eine Optimierung
indiziert sein. Bei dir wäre das die ID. Wenn das der Primary Key der Tabelle ist sollte das aber eigentlich schon sein. Außer man benutzt eine seltsame DB oder hat die Tabelle seltsam angelegt.

Warum ist der Tabellenname dynamisch in deinem Update? Es gibt zwar oft Anwendungen die Tabellen für bestimmte Daten dynamisch erzeugen, bearbeiten und wieder löschen. Ist aber in den meisten Fällen eher kontraproduktiv.

Zitat:
Die Spalte Dummy ist PK.


Dummy gibts in deinem Beispielen nicht.

Zitat:
Mit einem SqlBulkCopy habe ich es auch schon versucht, bekomme ab einer gewissen Größe
allerdings eine OutOfMemory Exception. ;-)


Regelmäßig commiten nicht vergessen und die Datenquelle über einen streamenden DataReader befüllen. Siehe SqlBulkCopy.EnableStreaming
CodingForBeer Threadstarter
Hält's aus hier
Beiträge: 7



BeitragVerfasst: Di 23.09.14 14:11 
Oh ja, Du hast recht!
Die Spalte Dummy gibt es nicht. ;-)

Typische Altlasten *peinlich*.
Die Spalte Dummy ist mittlerweile die Spalte ID.

Dynamisch ist bei mir der Tabellenname weil er aus einem Dateinamen erstellt wird
(nachdem nicht gewünschte Zeichen sowie die Dateiendung entfernt wurden).
Je nachdem wie viel Dateien im Verzeichnis sind, werden entsprechend viele
Tabellen erstellt.

Aber ich werde mich noch einmal eingehender mit dem SqlBulkCopy
und den Einstellungen zum TimeOut und der BatchSize beschäftigen.

Vielen Dank für die Info zum INDEX.
Auch das schau ich mir natürlich an. ;-)

Gruß
CfB