Abfrage beschleunigen
-
Hallo zusammmen!
Hat jemand einen Tipp für mich, wie ich folgende Abfrage beschleunigen kann?
In der relevanten Tabelle habe sind aktuell 460 Einträge, was an sich ja noch keine Menge ist. Dennoch dauert die Abfrage inzwischen ca. 10-15 Sekunden.for (int n = 0; n < dg.Rows.Count; n++) { // Prüfen ob WE komplett. if (Convert.ToBoolean(dg["WEabgeschlossen", n].Value) == true) { dg["WEabgeschlossen", n].Style.BackColor = Color.Green; } else { weTeilweiseAbgeschlossen = WareneingangKomplett(Convert.ToInt32(dg["idBestellungEK", n].Value)); if (weTeilweiseAbgeschlossen) { dg["WEabgeschlossen", n].Style.BackColor = Color.Yellow; } if (!weTeilweiseAbgeschlossen) { dg["WEabgeschlossen", n].Style.BackColor = Color.Red; } } } public bool WareneingangKomplett(int iBestellungEkId) { try { using (entity1 ctx = new entity1()) { var query = (from w in ctx.tblwareneingang_einzelheiten where w.bestellungen_ekId == iBestellungEkId select w).ToList(); if (query != null) { foreach (tblwareneingang_einzelheiten we in query) { // falls abgeschlossen. if (we.liefermengeAbgeschlossen) return true; else // falls zumindest Eintrag existiert. if (we.gelieferteMenge != 0) return true; } return false; } else return false; } } catch (Exception ex) { MessageBox.Show("Fehler: " + ex.Message); return false; ; } }
-
Niemand eine Idee???
-
Hi,
schau doch mal mit einem Profiler, wo genau der Flaschenhals im Code ist und wenn es wirklich das Query ist, dann schaust du welches Query an den SQL Server abgesetzt wird. Damit gehst du auf den SQL Server und prüfst den Ausführungsplan - möglicherweise fehlen Indizes.
Viele Grüße
KaPtainCugel
-
dein WareneingangKomplett wir dann 460 mal aufgerufen - das ist wirklich sehr ungeschickt - warum machst du nicht alles zusammen in einem Query (mit Join)?
aus welchem Query ergibt sich der dg.Rows.Count?
kannst du mal die relevanten Tabellen/Felder (und bitte auch nur diese - nicht alle) posten - damit man mal eine idealere SQL-Abfrage als Beispiel bauen kann
-
Vermutlich hast du auf
bestellungen_ekId
keinen Index.
Und vermutlich wäre es nochmal einiges schneller wenn du die ganze Funktion WareneingangKomplett im SQL Server machst und als berechnete Spalte mitgibst.
(-> z.B. View statt Table aufmachen)
-
und dann holst du dir in der WareneingangKomplett auch noch alle Felder um 2 davon zu pruefen - auch nicht wirklich sinnvoll
ich denke du kommst mit einem einzigen Query auf deine Green/Yellow/Red-Aussage - ohne so viel Schleifen und ifs in C# - lass die Datenbank auch ihre Fähigkeiten nutzen
-
select idBestellungEK, case WEabgeschlossen when 1 then 0 -- gruen when 0 then ( select case when exists ( select 1 from tblwareneingang_einzelheiten where bestellungen_ekId = idBestellungEK and (liefermengeAbgeschlossen = 1 or gelieferteMenge != 0) ) then 1 -- gelb else 2 -- rot end ) end as abgeschlossen_zustand from bestellungen
das Ergebnis
idBestellungEK abgeschlossen_zustand 1 1 2 2 3 0
fuer diese Tabellen
tblwareneingang_einzelheiten
(int)bestellungen_ekId (int)teilmenge (bit)liefermengeAbgeschlossen (int)gelieferteMenge 1 0 1 100 1 1 0 0 1 2 1 200 2 0 0 0 2 1 0 0 3 0 1 0 3 1 1 0 3 2 1 0
und
bestellungen
(int)idBestellungEK (bit)WEabgeschlossen 1 0 2 0 3 1
geht es noch kürzer?
-
public bool WareneingangKomplett(int iBestellungEkId) { try { using (entity1 ctx = new entity1()) { bool result = ctx.tblwareneingang_einzelheiten.Any( s => s.ekId == iBestellungEkId && ( s.liefermengeAbgeschlossen || s.gelieferteMenge != 0 ) ); return result; } } catch (Exception ex) { MessageBox.Show("Fehler: " + ex.Message); return false; ; } }
oder vorher die Tabelle materialisieren:
var query = (from w in ctx.tblwareneingang_einzelheiten where w.bestellungen_ekId == iBestellungEkId && ( w.liefermengeAbgeschlossen || w.gelieferteMenge != 0 ) select new { ID = iBestellungEkId } ).Distinct() .ToDictionary( s => s.ID, s => true );
und später abfragen
weteilweiseAbgeschlossen = query.ContainsKey( Convert.ToInt32(dg["idBestellungEK", n].Value) )
-
@SolidOffline - also meine Select kommt direkt auf das gruen,rot,gelb-Ergebnis - aber ich habe auch einfach Annahmen über seinen übergeordneten 460-Ids-Query gemacht
-
@Gast3
select
idBestellungEK,
case WEabgeschlossen
when 1 then 0 -- gruen
when 0 then
(
select
case when exists
(
select
1
from
tblwareneingang_einzelheiten
where
bestellungen_ekId = idBestellungEK
and (liefermengeAbgeschlossen = 1 or gelieferteMenge != 0)
) then 1 -- gelb
else 2 -- rot
end
)
end as abgeschlossen_zustand
from bestellungenSuper Sache! Funktioniert und läuft nun auch richtig schnell!! Herzlichen Dank für Deine Hilfe!
-
mir fehlte bei deinem Beispiel leider noch der Query mit dem du auf die 460 Rows am Anfang gekommen bist sonst hätte ich da noch weiter eingegrenzt - mein Select nimmt jetzt einfach alle
kann du noch hinschreiben welche Wheres zu deinen 460 Einträgen führen - oder waren es da auch einfach nur alle aus deinem Bestellungen-Table?