Der Grund dafür: PL/pgSQL behandelt SQL-Anweisungen als Prepared Statements intern.
Erstens: Mit Standardeinstellung gibt es keine Protokollierung von SQL-Anweisungen in PL/pgSQL alle Funktionen auf. Verwenden Sie auto_explain
?
Die ersten paar Anrufungen in der gleichen Sitzung erzeugt der SPI-Manager (Server Programming Interface) einen neuen Ausführungsplan, basierend auf tatsächlichen Parameterwerte. Jede Art der Protokollierung sollte Parameterwerte Inline melden.
Postgres verfolgt und nach ein paar Aufrufen in der aktuellen Sitzung, wenn Ausführungspläne nicht auf tatsächliche Parameterwerte reagieren, wird es beginnen, einen generischen, zwischengespeicherten Plan zu verwenden. Dann sollten Sie den generischen Plan einer vorbereiteten Anweisungen mit $n
Parameter (wie in der Frage) sehen.
Details in der chapter "Plan Caching" in the manual.
Sie können den Effekt mit einer einfachen Demo beobachten. In der gleichen Sitzung (nicht notwendigerweise gleiche Transaktion):
CREATE TEMP TABLE tbl AS
SELECT id FROM generate_series(1, 100) id;
PREPARE prep1(int) AS
SELECT min(id) FROM tbl WHERE id > $1;
EXPLAIN EXECUTE prep1(3); -- 1st execution
Sie werden den tatsächlichen Wert sehen:
Filter: (id > 3)
EXECUTE prep1(1); -- several more executions
EXECUTE prep1(2);
EXECUTE prep1(3);
EXECUTE prep1(4);
EXECUTE prep1(5);
EXPLAIN EXECUTE prep1(3);
Jetzt werden Sie einen $n
Parameter finden Sie unter:
Filter: (id > $1)
So können Sie die Abfrage mit Parameterwerten inline auf den ersten paar Aufrufen in der aktuellen Sitzung abrufen.
Oder Sie können, denn mit EXECUTE
, dynamischem SQL verwenden per documentation:
Außerdem gibt es keinen Plan Caching für über EXECUTE
ausgeführten Befehle. Stattdessen wird der Befehl immer bei jeder Ausführung der Anweisung geplant. Die Befehlszeichenfolge kann daher dynamisch innerhalb der Funktion erstellt werden, um Aktionen für verschiedene Tabellen und Spalten auszuführen.
Das kann natürlich die Leistung beeinflussen.
Verwandte:
Ich glaube nicht, dass Sie das Protokollformat ändern können. Anstatt zu versuchen, die Parameter selbst zu ersetzen, wäre es einfacher, die Abfrage über [PREPARE] (https://www.postgresql.org/docs/current/static/sql-prepare.html)/['auszuführen EXECUTE'] (https://www.postgresql.org/docs/current/static/sql-execute.html). Sie sollten in der Lage sein, diese Protokollzeilen in ein ausführbares Skript mit einer ziemlich einfachen Regex umzuwandeln. –
@NickBarnes, Danke. Scheint, dass ein Skript die einzige Lösung wäre. – Nulik
Sie können, falls notwendig, ['RAISE NOTICE'] (https://www.postgresql.org/docs/9.6/static/plpgsql-errors-and-messages.html) (oder ähnlich) in Ihrem Code hinzufügen, und Log dich ein, was nötig ist. – joanolo