Hallo,
habe in einer Transaktion mehrere Statements abzuarbeiten, wobei diese Transaktion unter PostgreSQL ca. 2 Minuten benötigt und als Vergleich mit der SQLBase von der wir Richtung PostgreSQL wechseln, die selbe Transaktion nur ca. 3 Sekunden benötigt.
Folgendes Statement wurde als der Flaschenhals identifiziert (habe mit der Entwicklungsumgebung im Debug/Animationsmodus jene Statements rausgepickt, bei denen die App auf das Ergebnis lange gewartet hat:
explain analyse select sum (coalesce(nettobetrag,0)-coalesce(rabattbetrag,0)), sum (coalesce(ustbetrag,0)),
sum (coalesce(bruttobetrag,0)), sum (1), sum(coalesce(is_ausgelifert,0)), sum(coalesce(is_fakturiert,0)),
sum (coalesce(ekwert,0)), sum (coalesce(anzeigenabgabe,0))
from sysadm.aufpos where auftraginr = 615404 and ebene = 0;
Wenn ich das Statement Analysiere komme ich auf Superkurze Antwortzeiten:
"Aggregate (cost=622.23..622.25 rows=1 width=75) (actual time=0.282..0.282 rows=1 loops=1)"
" -> Index Scan using xif23aufpos on aufpos (cost=0.00..619.01 rows=160 width=75) (actual time=0.026..0.033 rows=2 loops=1)"
" Index Cond: (auftraginr = 615404)"
" Filter: (ebene = 0)"
"Total runtime: 0.421 ms"
Die Anzahl der Datensätze die summiert werden sollen schwankt zwischen 1 - bis ca. 100, wobei der vorhandene Index benutzt wird.
Wie ist das möglich? Die PG läuft einem HP Dual Xenon 2,4GHz, 2GB Speicher auf einem Raid-1 System.
Das postgresql.conf File hat folgende Einstellungen:
port = 5432
max_connections = 100
shared_buffers = 256MB
maintenance_work_mem = 16MB
max_fsm_pages = 204800
fsync = on
effective_cache_size = 512MB
stats_start_collector = on
stats_row_level = on
autovacuum = on
Die restlichen Parameter sind auskommentiert.
Jeder Hinweis zur Beschleunigung der Kiste ist herzlich willkommen.
Hans
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Da hat akretschmer Recht, das kann nicht die problematische Stelle sein:
PostgreSQL denkt vorher, es braucht ungefähr 620 Plattenzugriffe, um das auszuführen (ANALYZE mal laufen lassen), effektiv ausgeführt werden kann das aber in einem Plattenzugriff. Alles in allem sind selbst die geschätzten 600 Zugriffe in ein paar Millisekunden erledigt, dass das ganze noch schneller ist, siehst du ja an der Ausführungszeit.Code:(cost=622.23..622.25 rows=1 width=75) (actual time=0.282..0.282 rows=1 loops=1)
Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören
Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler
PostgreSQL Service & Support
habe ANALYZE auf die betreffende Datenbank ausgeführt. Beim erstenmal dauert obige Transaktion ca. 1 min, beim 2-ten...n-ten mal ausführen can 15 sec.
Da muß es doch noch einige Schrauben geben, an denen man drehen kann.
Ich kann nicht glauben, dass die PG (lt. Performance Test vom Juli/2007 12% langsamer als Oracle und 10% schneller als MySql) von einer Pimperldatenbank wie der SQLBase überholt wird (Datenbankgröße 5GB, in 3 Tabellen die in die Transaktion involviert sind, existieren jeweils ca. 1,2 - 1,4 Mio Datensätze).
Was sagt Ihr dazu?
Gruß
Hans
Wir sagen dazu: wir haben keine Ahnung, wie deine Datenbank aufgebaut ist.
Ausserdem haben wir aufgezeigt, das die Stelle von der du dachtest das sie ein Problem ist, das nun genau nicht ist.
Also muss dein Problem woanders liegen ;-)
Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören
Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler
PostgreSQL Service & Support
Zu was?
PG braucht *etwas* Pflege in Form von VACUUM und ANALYSE, aber das sollte kein Problem darstellen. Ansonsten muß man halt das Select und die Meinung von EXPLAIN ANALYSE dazu betrachten. Es gibt Anwender, die haben etliche Zehnerpotenzen mehr Daten in ihrem System und keine Probleme.
Andreas
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Ich hab jetzt mal die Statements beisammen mit der Analyse. Beim Update habe ich nur zwei statt den zwanzig Spalten genommen (war etwas mühselig die einzelnen Werte aus de Bindvariablen zu holen), es geht aber über den PK wobei ein Rowlvel Trigger gefeuert wird um die roversion zu prüfen ob sie noch gleich ist wie vor dem Update (wenn ja, wir um eins weitergezählt, wenn nein: bekommt der User eine Meldung (raise exception) daß jemand anderer die gleiche row bereits geändert hat.
Die Werte:
select distinct lsinr from sysadm.lieferschein where auftraginr = 615344;
"Unique (cost=8.74..8.77 rows=6 width=8)"
" -> Sort (cost=8.74..8.75 rows=6 width=8)"
" Sort Key: lsinr"
" -> Index Scan using lief_auftraginr on lieferschein (cost=0.00..8.66 rows=6 width=8)"
" Index Cond: (auftraginr = 615344)"
select max (a.ebene) from sysadm.aufpos a, sysadm.rechpos r
where a.auftraginr = 615344 and r.reinr =3243143 and a.auftraginr = r.auftraginr and a.aufposinr = r.aufposinr;
"Aggregate (cost=592.54..592.55 rows=1 width=8)"
" -> Nested Loop (cost=0.00..592.53 rows=1 width=8)"
" -> Index Scan using xif51rechpos on rechpos r (cost=0.00..584.13 rows=1 width=16)"
" Index Cond: (reinr = 3243143)"
" Filter: (auftraginr = 615344)"
" -> Index Scan using xpkaufpos on aufpos a (cost=0.00..8.39 rows=1 width=24)"
" Index Cond: (a.aufposinr = r.aufposinr)"
" Filter: (auftraginr = 615344)"
select kurs_1, kurs_2, eingabewaehrung, p_sonder_rabatt, rowversion
from sysadm.auftrag where auftraginr =615344;
"Index Scan using xpkauftrag on auftrag (cost=0.00..8.29 rows=1 width=45)"
" Index Cond: (auftraginr = 615344)"
select sum (coalesce(nettobetrag,0) - coalesce(rabattbetrag,0)), sum (coalesce(ustbetrag,0)),
sum (coalesce(bruttobetrag,0)), sum (1), sum(coalesce(is_ausgelifert,0)), sum(coalesce(is_fakturiert,0)),
sum (coalesce(ekwert,0)), sum (coalesce(anzeigenabgabe,0))
from sysadm.aufpos where auftraginr = 615344 and ebene = 0;
"Aggregate (cost=594.98..594.99 rows=1 width=75)"
" -> Index Scan using xif23aufpos on aufpos (cost=0.00..591.78 rows=159 width=75)"
" Index Cond: (auftraginr = 615344)"
" Filter: (ebene = 0)"
select sum (coalesce(netto_abzgl_rab,0)), sum (coalesce(netto_abzgl_rab_1,0)), sum (coalesce(netto_abzgl_rab_2,0))
from sysadm.lieferschein where auftraginr = 615344;
"Aggregate (cost=8.71..8.72 rows=1 width=34)"
" -> Index Scan using lief_auftraginr on lieferschein (cost=0.00..8.66 rows=6 width=34)"
" Index Cond: (auftraginr = 615344)"
UPDATE sysadm.auftrag SET wert_auftrag = 89,03, rowversion = 4 WHERE auftraginr = 615344;
"Index Scan using xpkauftrag on auftrag (cost=0.00..8.29 rows=1 width=1083)"
" Index Cond: (auftraginr = 615344)"
So wie es aussieht muß es wohl am ODBC Treiber liegen. Meiner hat die Version 8.2.4 vom 27.04.2007
Liege ich mit meiner Vermutung richtig?
Gruß
Hans
Links: Tobias Bauer - IT- und Funkdienstleistungen - Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen - Funkforum
Lesezeichen