Forum: PC-Programmierung Programm fängt an "langsam" zu werden.


von Andreas (Gast)


Lesenswert?

Hi,

ich habe ein kleines Programm welches echt super funktioniert, aber 
leider wird das ziemlich schnell langsam...

Der Fehler ich "reproduzierbar" ... sicherlich Erzeug ich irgendwo im 
Hintergrund Daten ohne ende oder so, evtl. hat jemand einen Tipp für 
mich.

ich habe eine kleine Methode welche einen Datenbankabruf macht und 5 
Zeilen aus der Datenbank holt... <- da hier Millionen schlecht 
indizierte Daten sind, dauert das ganze fast 5 Sekunden (ist aber nicht 
das Problem).

1
        public static DataTable Sql2DataTable(string tns, string query)
2
        {
3
            DataTable result = new DataTable();
4
            try
5
            {
6
                using (OracleConnection dbConnection = new OracleConnection(tns))
7
                {
8
                    OracleCommand command = dbConnection.CreateCommand();
9
                    command.CommandText = query; 
10
                    dbConnection.Open();
11
                    using (OracleDataReader reader = command.ExecuteReader())
12
                    {
13
                        result.Load(reader);
14
                    }
15
                    dbConnection.Close();
16
                }
17
            }
18
            catch (Exception ex)
19
            {
20
                MessageBox.Show(ex.Message);
21
            }
22
            return result;
23
        }

anschließend werden die Daten über ein Binding direkt an ein eine 
DataTable gebunden...

als Hauptprogramm habe ich eine DataTable mit ~200 Zeilen, wenn man eine 
Zeile anklickt, wird diese "geöffnet" und es erscheint eine 
"Mini-Tabelle" in welcher die 5 Zeilen geladen werden...

Das Laden mache ich (wie oben bereits erwähnt) über ein Binding im 
DataGrid:
ItemsSource="{Binding Path=ID, Converter={StaticResource dataReader}, 
ConverterParameter=prm,IsAsync=True,FallbackValue='Please Wait'}"

Das funktioniert das 1. mal perfekt! Das 2. mal (also wenn ich eine 2. 
Datenzeile anklicke) etwas langsamer und das 3. mal merkt man schon 
deutlich, dass z.B. das Scrollen durch die Hauptliste langsamer wird 
(dabei habe ich einen i7 und 16GB RAM).

kann man hier schon eine Aussage treffen? oder welche Informationen 
müsste ich noch liefern?

von Daniel -. (root)


Lesenswert?

Dann zeig doch das Hauptprogramm und nicht die irrelevante Funktion

von Andreas (Gast)


Lesenswert?

was willst du denn sehen?

mehr code gibt es nicht...

das Hauptprogram hat damit rein GARNICHTs zu tun... wie schon gesagt, 
das geht über ein BINDING <- und das läuft auch schief, wenn das 
Hauptprogramm nicht existent ist... (mal abgesehen von den Daten für die 
Datenbank TNS & Query)

von Andreas (Gast)


Lesenswert?

Fehler gefunden... leider weiß ich noch nicht wie ich es lösen kann...

Das Binding löst öfters einen "DB" abruf aus... und immer wenn der 
DB-Abruf ausgelöst wird, dauert es 5 sekunden bis die werte da sind...

das macht er komischerweise beim 1. mal nicht, beim 2. mal selten und ab 
den 3. mal sehr oft.

Wie kann ich mein Binding Cachen oder wie kann ich eine DataTable 
Cachen?

von Ingo D. (ingo2011)


Lesenswert?

Hi ,

zeig doch mal Dein Select (query). Wenn ich oben lese "hier Millionen 
schlecht indizierte Daten" , dann muss man hier erstmal ansetzen das 
Design zu ueberarbieten ... wenn jedesmal ein Full table scan gemacht 
werden muss ist das klar, das es langsam ist ...

Gruß Ingo

von Der Andere (Gast)


Lesenswert?

By the way, wenn in den Aufrufen
  reader = command.ExecuteReader()
  result.Load(reader);
eine Exception geworfen wird, dann bleibt deine Connection endlos offen.
Das close() gehört in ein finally!

von Andreas (Gast)


Lesenswert?

keine Angst, der Select ist perfect

ich bin Oracle Datenbankdeveloper... an den kann man nichts mehr 
verbessern und außerdem läuft dem im SQL-Developer gleichschnell!

die 5 Sekunden sind und bleiben...
=> und selbst wenn es 0.5 Sekunden wären, würde das Tool amok laufen, 
wenn ständig neue Daten erfragt werden, obwohl die Informationen bereits 
gegeben sind.

=> hier muss das Binding angepasst werden oder die Daten gecached...

Beitrag #5265661 wurde von einem Moderator gelöscht.
Beitrag #5265671 wurde von einem Moderator gelöscht.
von Der Andere (Gast)


Lesenswert?

Andreas schrieb:
> Das Binding löst öfters einen "DB" abruf aus... und immer wenn der
> DB-Abruf ausgelöst wird, dauert es 5 sekunden bis die werte da sind...
>
> das macht er komischerweise beim 1. mal nicht, beim 2. mal selten und ab
> den 3. mal sehr oft.
>
> Wie kann ich mein Binding Cachen oder wie kann ich eine DataTable
> Cachen?

Indem du dich an Design Regeln hältst:
https://msdn.microsoft.com/en-us/library/ee658109.aspx

Sorge dafür daß du deine "Sql2DataTable" Methode nur aufrufst wenn du 
wirklich neue Daten brauchst. Wenn du den Aufruf irgendwo im 
Presentation Layer versteckst wo du keine Kontrolle darüber hast:

Andreas schrieb:
> Das Laden mache ich (wie oben bereits erwähnt) über ein Binding im
> DataGrid:

dann musst du dich nicht wundern wenn der Aufruf auch dann geschieht 
wenn du nicht damit rechnest. Also packe die Daten in eine gepufferte 
Struktur die nur dann die Daten durch ein Query auf die Datenbank 
aktualisiert wenn du das für richtig und notwendig hältst. Dein Grid 
erhält dann die Daten über deinen Puffer.

Andreas schrieb:
> keine Angst, der Select ist perfect
>
> ich bin Oracle Datenbankdeveloper... an den kann man nichts mehr
> verbessern

Sorry aber zu dem Spruch fällt mir spontan das hier ein:
https://de.wikipedia.org/wiki/Dunning-Kruger-Effekt

von Walfänger (Gast)


Lesenswert?

Oracle ist eben nicht mehr der Nabel der Welt, wenn es um schnelle 
Datenbanken geht. Es gibt auch welche, die finden die 5aus10^6 Sätze 
über eine nicht-indizierte Spalte in 5ms.

von P. P. (Gast)


Lesenswert?

In deinem Quelltext baust du bei jeder Anfrage eine neue 
Datenbankverbindung auf. Das geht manchmal schnell, und oft dauert's ein 
paar Sekunden, weil Oracle wieder alles neu intialisieren muss.

Empfehlenswert wäre, wenn du die Connection nur einmal aufmachst und 
dann für jeden SQL-Request wiederverwendest (pufferst).

Weiterhin empfiehlt sich ein Pooling der Connections, falls du mehrere 
SQLs gleichzeitig parallel an Oracle schickst. Dafür kann man z.B. c3pO 
gut und schnell einbinden.

Gruß Pirx

von abc (Gast)


Lesenswert?

Andreas schrieb:
> Das funktioniert das 1. mal perfekt! Das 2. mal (also wenn ich eine 2.
> Datenzeile anklicke) etwas langsamer und das 3. mal merkt man schon
> deutlich, dass z.B. das Scrollen durch die Hauptliste langsamer wird
> (dabei habe ich einen i7 und 16GB RAM).

Für ausnahmslos jede Programmiersprache gibt es Profiler.

Wie wäre es, wenn du dein Programm mal profilierst?

Beitrag #5267139 wurde von einem Moderator gelöscht.
von stnv (Gast)


Lesenswert?

Andreas schrieb:
>ich habe eine kleine Methode welche einen Datenbankabruf macht und 5
>Zeilen aus der Datenbank holt... <- da hier Millionen schlecht
>indizierte Daten sind, dauert das ganze fast 5 Sekunden (ist aber nicht
>das Problem).

>Das funktioniert das 1. mal perfekt! Das 2. mal (also wenn ich eine 2.
>Datenzeile anklicke) etwas langsamer und das 3. mal merkt man schon
>deutlich, dass z.B. das Scrollen durch die Hauptliste langsamer wird
>(dabei habe ich einen i7 und 16GB RAM).

>das macht er komischerweise beim 1. mal nicht, beim 2. mal selten und ab
>den 3. mal sehr oft.

>ich bin Oracle Datenbankdeveloper

Aus diesen Angaben würde ich folgendes schlussfolgern:

Die OracleDB ist nicht optimal auf dem Rechner eingerichtet. Da hilft 
auch kein Profiling. Dieses würde wahrscheinlich bei diesen Zeiten 
einfach sagen "Fulltablescan".

Die Datenbank hat standartmäßig heute ein dynamisches Speichermanagement 
(ab 10g). Dieses paßt den Speicher und damit die Möglichkeiten den Cache 
zu nutzen schnell wieder zu nichte. Gerade auf nicht sehr stark 
frequentierte "Developer Datenbanken".

Das würde auch die eigentümlichen Geschwindigkeitssprünge erklären.


Aus Sicht der Datenbank:

Ja. Eine Tabelle kann in den Cache kommen. Dies ist standardmäßig nicht 
aktiv. Die Daten altern sehr schnell raus.
(ALTER TABLE ... CACHE)

Wenn hier schon eine 16 GByte Maschine vorliegt dann schenke der 
Datenbank Speicher damit sie cachen kann. Falls es eine Express Version 
(max 1 GByte) ist, dann installiere ein richtige Version, sie kann für 1 
Monat frei genutzt werden. Somit kann die Geschwindigkeitsoptimierung 
mal geprüft werden.
(ALTER SYSTEM ...)

Schalte das dyn. Speichermanagement mal aus. Damit bleibt der Speicher 
durch die DB im Zugriff und es können die Daten aus dem Cache wieder 
verwendet werden.
Daher fixe Speicherverwaltung. Ich würde testweise mal 8GByte zuweisen.
(ALTER SYSTEM ...)

Das sollte im Idealfall dann beim 1. mal durch die physikalischen 
Lesezugriffe etwas langsamer sein. Dann sollten nur noch logische 
Lesezugriffe erfolgen. ergo. Ab dem 2. mal sollten die Daten schneller 
da sein.
Viel wichtiger: Die DB würde "konstanter" reagieren.


Wenn das mal produktiv gehen sollte...
Setz Dich mit einem DBA zusammen und überlegt wie die zukünftige 
Instance der DB aussehen soll. Das Thema Index würde ich auch noch mal 
angehen. Oracle bietet hier einiges. Und dann würde auch ein Profiler 
wieder interessant werden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.