Kann die Deklaration der Funktionsvolatilität IMMUTABLE die Leistung beeinträchtigen?


9

Postgres - Funktionen werden mit deklarierten Volatilität Klassifizierung VOLATILE, STABLEoderIMMUTABLE . Es ist bekannt, dass das Projekt mit diesen Bezeichnungen für integrierte Funktionen sehr streng ist. Und das aus gutem Grund. Prominentes Beispiel: Ausdrucksindizes erlauben nur IMMUTABLEFunktionen und diese müssen wirklich unveränderlich sein, um falsche Ergebnisse zu vermeiden.

Benutzerdefinierte Funktionen können weiterhin nach Wahl des Eigentümers deklariert werden. Das Handbuch empfiehlt:

Um optimale Optimierungsergebnisse zu erzielen, sollten Sie Ihre Funktionen mit der strengsten Volatilitätskategorie kennzeichnen, die für sie gültig ist.

... und fügt eine umfangreiche Liste von Dingen hinzu, die mit einem falschen Volatilitätsetikett schief gehen können.

Dennoch gibt es Fälle, in denen eine Fälschung der Unveränderlichkeit sinnvoll ist. Meistens, wenn Sie wissen, dass die Funktion in Ihrem Anwendungsbereich tatsächlich unveränderlich ist. Beispiel:

Abgesehen von allen möglichen Auswirkungen auf die Datenintegrität , wie wirkt sich dies auf die Leistung aus? Man könnte annehmen , eine Funktion deklarieren IMMUTABLEkann nur von Vorteil sein , die Leistung . Ist das so?

Kann die Angabe der Funktionsvolatilität IMMUTABLE die Leistung beeinträchtigen ?

Nehmen wir an, dass das aktuelle Postgres 10 eingrenzt, aber alle neueren Versionen sind von Interesse.


1
Auch als Randnotiz ist das Ganze "wirklich unveränderlich" auf Ausdrucksindizes eine echte Pita. Das ist eine schreckliche Benutzeroberfläche. Wir sollten in der Lage sein, FORCEsie so oder so zu erreichen. 100% der erfahrenen PostgreSQL-Datenbankadministratoren arbeiten daran, diese Benutzeroberfläche mit Wrapper-Funktionen zu umgehen. Zumindest mit FORCEwürden wir keine Wrapper brauchen und wir müssten uns nicht auf die erklärte Volatilität von fn stützen.
Evan Carroll

1
Ich gehe davon aus FORCE, dass Ausdrucksindizes nicht unveränderliche Funktionen akzeptieren sollen (während sie als potenzieller Fehlerpunkt markiert werden). Ja, das scheint eine elegantere Lösung zu sein als unveränderliche Funktions-Wrapper.
Erwin Brandstetter

Ich weiß fast nichts über PostGres, aber ist Volatilität nicht überflüssig? Was bedeutet das? Erwarten Sie im Ernst nicht, dass dies zuverlässig ist, denn es ist verrückt ?
Anthony

@ Anthony: Ich habe noch etwas geklärt. Folgen Sie dem Link zum Handbuch für Details.
Erwin Brandstetter

Antworten:


7

Ja, dies kann die Leistung beeinträchtigen.

Einfache SQL-Funktionen können in der aufrufenden Abfrage "eingebunden" werden. Zitieren des Postgres-Wikis :

SQL-Funktionen (dh LANGUAGE SQL) haben unter bestimmten Bedingungen ihre Funktionskörper in die aufrufende Abfrage eingebunden, anstatt direkt aufgerufen zu werden. Dies kann erhebliche Leistungsvorteile haben, da der Funktionskörper dem Planer der aufrufenden Abfrage ausgesetzt wird, der Optimierungen wie Konstantfalten, Qual-Pushdown usw. anwenden kann.

Meine kühne Betonung.

Um die Richtigkeit durchzusetzen, gibt es eine Reihe von Voraussetzungen. Einer von ihnen :

Wenn die Funktion deklariert ist IMMUTABLE, darf der Ausdruck keine nicht unveränderlichen Funktionen oder Operatoren aufrufen

Das heißt, SQL-Funktionen, die nicht unveränderliche Funktionen verwenden, aber noch deklariert IMMTUTABLEwerden, sind von dieser Optimierung ausgeschlossen. Ausgelöst durch diese verwandten Antworten auf SO habe ich umfangreiche Tests durchgeführt:

Grundsätzlich werden diese beiden Varianten einer einfachen SQL-Funktion verglichen (Zuordnen von Daten zu einem integer, Ignorieren des Jahres, das für den Zweck keine Rolle spielt):

CREATE FUNCTION f_mmdd_tc_s(date) RETURNS int LANGUAGE sql STABLE    AS
$$SELECT to_char($1, 'MMDD')::int$$;

CREATE FUNCTION f_mmdd_tc_i(date) RETURNS int LANGUAGE sql IMMUTABLE AS
$$SELECT to_char($1, 'MMDD')::int$$;  -- cannot be inlined!

Die Postgres-Funktion to_char()ist nur STABLEnicht IMMUTABLE(alle überladenen Instanzen davon - aus Gründen, die über den Rahmen dieser Antwort hinausgehen ). Der zweite ist also eine Fälschung IMMUTABLEund stellt sich in einem einfachen Test als 5x langsamer heraus :

db <> hier fummeln

Dieses spezielle Beispiel kann durch das Äquivalent ersetzt werden:

CREATE FUNCTION f_mmdd(date) RETURNS int LANGUAGE sql IMMUTABLE AS
$$SELECT (EXTRACT(month FROM $1) * 100 + EXTRACT(day FROM $1))::int$$;

Würde scheint teurer mit zwei Funktionsaufrufen und mehr Berechnungen. Aber das IMMUTABLEEtikett ist wahr (plus, ist die verwendete Funktion schneller und Nötigung textzu integerteurer, auch).

2x so schnell wie die oben genannte schnellere Variante (10x so schnell wie die langsamere). Der Punkt ist: Verwenden Sie IMMUTABLEFunktionen, wo dies möglich ist , dann müssen Sie zunächst nicht "schummeln".


Coole Ergebnisse! Verfolgen Sie es sofort: dba.stackexchange.com/q/212198/2639
Evan Carroll

Sie wissen, was ich hier vermisst habe, was ich nicht wusste. Das STABLEist auch Inlining. Ich dachte, der Optimierer würde nur Online- IMMUTABLEFunktionen.
Evan Carroll

VOLATILEgenausogut.
Erwin Brandstetter

Das Wiki sagt, dass die Funktion als STABLE oder IMMUTABLE deklariert
Evan Carroll

.. unter "Inlining-Bedingungen für Tabellenfunktionen ". Nicht für Skalarfunktionen. Ich habe es in der Geige demonstriert: dbfiddle.uk/…
Erwin Brandstetter
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.