Hallo Leute,
ich verstehe es einfach nicht. Ich hole aus einer MySQL Datenbank mittels Abfrage meine Datensätze und schreibe diese in eine DataTable.
Dann hole ich für jeden Eintrag in der DataTable noch zuätzliche Details per Abfrage.
foreach (DataRow r in dt.Rows)
{
SQL = "select * from tabelle where id = " + r["twa_code"].ToString();
using (MySqlCommand cmd = new MySqlCommand(SQL, ACon))
{
using (MySqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
int a = dt.Columns.IndexOf("part_nr_twa");
int b = dr.GetOrdinal("part_nr_TWA");
//r[a] = dr[b];
//r["part_nr_rim"] = dr["part_nr_rim"];
//r["part_nr_tyre"] = dr["part_nr_tyre"];
//r["part_nr_valve"] = dr["part_nr_valve"];
//r["tyre_manufacturer"] = dr["tyre_manufacturer"];
//r["rim_manufacturer"] = dr["rim_manufacturer"];
}
dr.Close();
dr.Dispose();
}
cmd.Dispose();
}
Nun das kuriose: diese Zuweisung von datareader zu Datarow der Datatable dauert sehre lange. Ich dacht erst, es dauert so lange dass die Row als auch Datareader den Index der Spalte zu finden. Deshalb habe ich versucht den Index vorher zu ermitteln. Das war es nicht, aber wenn ich die Zuweisung r[a] = dr**; auskommentiere vervielfacht sich die Geschwindigkeit. Wie kann ich die Zuweisung anders gestalten??
Danke Tossi
Hallo Tossi65,
kann es sein das du mit "dr**" auf eine Lazy-Property zugreifst und er sich die Daten erstmal noch aus der DB holen muss? Wenn ja, dann musst du die Sachen nur Eager laden.
MfG
Rabban
Wo ich deine Where-Bedingung so sehe: Bitte dringend mal [Artikelserie] SQL: Parameter von Befehlen angucken (und anwenden).
Warum machst du...
dr.GetOrdinal("part_nr_TWA");
dr[b];
...und nicht...
dr["part_nr_TWA"];
Ansonsten:
Wie groß ist der Inhalt von part_nr_twa
?
Ist die Zuweisung an r[a]
langsam oder das Auslesen aus `dr**[/tt]?
Wahrscheinlich läuft es auch auf ein N+1-Problem hinaus.
Hi,
um die Sache zu beschleunigen, würde ich die Tabellen über ein View verknüpfen und dann den View auslesen, damit sparst du Selects auf die DB, die Zeit kosten.
Gruß Ron
Hi,
das ganze dauert so lange, weil da Du für jedes einzelne Element eine eigene DB-Verbindung aufbaust (Overhead Verbindungsaufbau), dann einzelne Datensätze abfragst (synchrone SQLs), das SQL nicht per Parameter Variabilisierst (Schlecht für den Optimizer) und alle Spalten selektierst, auch wenn Du möglicherweise nicht alle brauchst (verhindert Index-only Zugriffe).
Falls dt auch aus der gleichen Datenbank kommt solltest Du die Tabellen am besten Joinen (geht z.B. auch mit einer View, aber auch ohne). Wenn nicht kannst Du auch alle Daten aus der Tabelle in eine DataTable laden und per Linq Joinen.
Allerdings halte ich die Schleife auch für etwas komisch; Jede Datarow r bekommt nacheinander die Werte aller Rows von dr zugewiesen! Der Sinn erschließt sich mir nicht. Sollten nicht die für jede Row von dr eine neue Row von r erzeugt werden (eben ein inner join)?
Gruß
f-igy
Hallo Tossi65,
es geht mittels der Klasse DataAdapter viel einfacher:
MySqlDataAdapter = new MySqlDataAdapter("SELECT * FROM TableName", connectionstring)
DataTable dataTable = new DataTable();
MySqlDataAdapter.fill(dataTable);
Und für verknüpfte Tabellen ist, wie schon geschrieben, das Stichwort: Inner joins, z.B.
SELECT * FROM TableName1, TableName2 where TableName1.Id1 = TableName.Id2
Danke für die schnellen Antworten, aber ihr liegt daneben.
@dN!3L
das habe ich gemacht, weil ich dachte damit das Problem zu finden.
@f_igy
ich hatte einen join, aber wir nutzen eine MySql Clusterdatenbank und die mögen joins nicht so gerne.
Bei sehr vielen Daten reicht der Speicher nicht. Wir haben extrem viel Daten.
Ich baue nur eine Verbindung vor dem foreach .... auf und es liegt nicht an der Query. Wenn ich
die Zuweisung komplett auskommentiere und trotzdem aber die Daten aus der Datenbank hole,
geht es rasend schnell. Wenn ich aber die Daten zuweise dauert die Zuweisung ca. 2 sek pro Spalte.
Dadurch wir die Abfrage sehr langsam und dauert bei ca. 4000 Datensätze weit über 10 Minuten
Ohne Zuweisung und die gleiche Datenmenge ca. 2 Minten!!!!
Danke Tossi
Dann liegt es an deiner DataTable dt.
Ist die vielleicht an ein Control gebunden?
Dann wird nämlich bei jedem zuweisen dieses Control refreshed.
Ansonsten, "SELECT *" ist sehr ineffectiv, zumal du ja die Spaltennamen kennst.
Du hast anscheinend nicht gesehen das er da für jede Row neue Daten anfordert.
Danke Euch allen, dass habe ich nun hinbekommen. Das Daten holen ist nun ein klacks.
Nun hat sich das Problem verlagert. Ich lade alle Daten in ein DataTable.
Wenn ich fertig bin, mache ich folgende Zuweisung:
GV.DataSource = DatatTable
Bei ca. 5000 Datensätzen dauert das Anzeigen ca. 3 Minuten: Kann ich das ändern???
In Delphi gibt es die Verzögerung nicht!
Danke Tossi