1

Wenn eine Anweisung in meiner PLPGSQL Funktion (Postgres 9.6) ausgeführt wird, kann ich die Abfrage in einer Zeile sehen, und dann alle Parameter in einer anderen Zeile. Eine 2-Zeilen-Protokollierung. Etwas wie:Wie loggen Abfragen in PLPGSQL mit inline Parameterwerte

LOG: execute <unnamed>: SELECT * FROM table WHERE field1=$1 AND field2=$2 ...  
DETAIL: parameters: $1 = '-767197682', $2 = '234324' .... 

Ist es möglich, die gesamte Abfrage in pg_log MIT die Parameter bereits in der Abfrage ersetzt und melden Sie es in einer SINGLE Linie anmelden?

Da dies es viel einfacher machen würde, die Abfrage zu kopieren, um sie in einem anderen Terminal zu reproduzieren, besonders wenn Abfragen Dutzende von Parametern haben.

+0

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. –

+0

@NickBarnes, Danke. Scheint, dass ein Skript die einzige Lösung wäre. – Nulik

+0

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

Antwort

1

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: