2014-06-16 3 views
10

Ich versuche, meine Funktion zu optimieren.
Die Sache ist, wenn Sie die Abfrage ausführen, sobald Sie ein Ergebnis erhalten.
Führen Sie die Abfrage ein zweites Mal oder zum dritten Mal die Prozesszeit ist viel kleiner.Wie deaktiviert postgresql "Cache" -Optimierung?

SELECT map.get_near_link(a.X, a.Y, a.azimuth) 
FROM traffic.avl; 

Zum ersten Mal 17 seg

Total query runtime: 17188 ms. 
801 rows retrieved. 

zum zweiten Mal 11 seg

Total query runtime: 11406 ms. 
801 rows retrieved. 

Ich vermute, es irgendeine Art von Cache ist Optimierung hinter Szene zu tun. Wie kann ich dieses Verhalten deaktivieren, damit ich einen realistischeren Laufzeitwert bekommen kann?

+0

Ich denke, Sie können davon ausgehen, dass das zweite Ergebnis realistischer als das erste ist. – klin

+0

Nun, in der Theorie nehme ich an, dass x, y, Azimut in jeder Abfrage unterschiedlich sein wird, weil es sehr anders ist als ein zweiter Benutzer die exakten Werte eingibt. Also ich denke, der erste Wert ist der Realist. Jedenfalls, wenn ich den Code in der Funktion ändere, muss ich alle Tests mehrmals ausführen, um sicherzustellen, dass man den Durchschnittswert hat. –

+0

Als ich bei Postgres nichttriviale Tests machte, erfuhr ich, dass die Standardabweichung des ersten Ergebnisses fast immer die größte war. Daher akzeptierte ich den Grundsatz, das erste Ergebnis zu überspringen. Ich denke, du musst deine Funktion mit zufälligen Argumenten testen. – klin

Antwort

11

PostgreSQL hat keine "Cache" -Optimierung im Sinne eines Abfrageergebnis-Cache.

Es tut Cache-Tabellenblöcke, die kürzlich in shared_buffers gelesen wurden, aber für die meisten Installationen, die nur einen kleinen Effekt hat. Der Hauptcache ist der Disk Read Cache des Betriebssystems. Für weitere Informationen siehe:

See and clear Postgres caches/buffers?

Es klingt für mich wie Sie ein System mit einer angemessenen Menge an RAM und einer schnellen CPU, sondern eine schrecklich langsam Platte. Daher sind Abfragen, die nur den Festplatten-Cache des Betriebssystems betreffen, sehr schnell, aber Abfragen, die auf die Festplatte gehen, benötigen ein paar Sekunden, um die Daten einzulesen. Daher sind Caching-Effekte sehr stark.

Sie sollten explain (buffers, analyze, verbose) SELECT ... Ihre Abfragen. Versuchen Sie es mit ein paar verschiedenen Eingabewerten, bis Sie eine langsame erhalten. Pläne vergleichen.

Wenn die Pläne die gleichen sind, ist es wahrscheinlich.

Wenn die Pläne anders sind, treffen Sie wahrscheinlich eine Situation, in der der Abfrageplaner basierend auf Variationen in den Tabellenstatistiken falsche Entscheidungen trifft. Das Erhöhen der Statistikziele für die interessierenden Spalten kann hilfreich sein (siehe Handbuch). Wenn du andere Pläne hast und feststeckst/Hilfe brauchst, kannst du eine neue Frage auf dba.stackexchange.com mit Details posten.

+0

Nach dem Lesen Ihrer Antwort habe ich etwas nachgedacht und sieht aus wie meine Probleme sind, weil eine langsame Festplatte. Ich musste keine zufälligen Werte ausprobieren, die Funktion wird bereits 500 mal/min aufgerufen und ich zeichne die Prozesszeit für jeden auf. Meine Hauptidee war, die Fälle zu replizieren, wenn ein 'function (x, y, z)' Aufruf mehr als 2000 ms dauert, wenn normalerweise nur 30 ms dauern. Aber nachdem ich die Log-Datei angeschaut und das 'explain' für jeden Fall überprüft hatte, bekam ich immer das gleiche Ergebnis und konnte das langsame Verhalten nicht duplizieren. Also denke ich, in diesen Fällen ist es eher so, dass die Verzögerung von einer ausgelasteten Festplatte verursacht wurde, als von einem schlechten Index. Vielen Dank. –

1

Da Sie gesagt haben, Sie möchten Ihre Funktion optimieren, nicht Ihr Festplattenlayout, dann sind die 2. Timings wahrscheinlich diejenigen, auf die Sie sich konzentrieren wollen, da sie das reinste Maß für die Laufzeit Ihrer Funktion sind und nicht die Zeit, die benötigt wird, um die Daten für Ihre Funktion zu erfassen.

Und da die zweite Ausführungszeit immer noch 2/3 der ersten Ausführungszeit ist, wäre das immer noch der Punkt, an dem Sie Ihre Aufmerksamkeit richten sollten, auch wenn Sie die gesamte Ausführungszeit optimieren möchten.

Wenn Sie dies wirklich tun müssen, können Sie den Cache löschen, wie in einer anderen Antwort erklärt, aber das ist normalerweise zu mühsam, um für Routinearbeiten verwendet zu werden. Besser wäre es, ein Programm/Skript zu erstellen, das zufällige (aber im Allgemeinen realistische) Werte von a.X, a.Y, a.azimuth auswählt und die Abfrage mit ihnen ausführt. Indem Sie die Werte jedes Mal aus einer Reihe von Realitätsbeispielen ändern, erhalten Sie Ergebnisse, die für die reale Welt am repräsentativsten sind. Solche Fahrer zu machen ist ein wenig mehr Arbeit im Voraus, aber in der Regel zahlt sich aus.

+0

Ich hatte das gleiche Problem und, sogar ist wahr, dass ich meine Funktion optimieren möchte, kann ich nicht mein Disk-Layout ändern, so dass ich meine Funktion unter den schlechtesten Bedingungen testen muss. Das heißt: wenn keine Daten im Cache sind, weil ich die Reihenfolge der Abfragen und anderer Dinge ändern kann, um die schlimmsten Fälle zu vermeiden. Aber ich muss es mehrmals testen können. – bitifet

8
sync; sudo service postgresql stop; echo 1 > /proc/sys/vm/drop_caches; sudo service postgresql start 
+0

Es ist sehr hilfreich – ilgam

+0

Danke für den Tipp, das ist derzeit die Möglichkeit, den Cache und Puffer zu löschen. –