PL / PgSQL- und einfache SQL-Funktionen sind beide Teil eines größeren Werkzeugsatzes und sollten in diesem Zusammenhang betrachtet werden. Ich neige dazu, es in einem aufsteigenden Leistungsmaßstab zu sehen, der mit steigender Komplexität und steigenden Kosten einhergeht, wobei Sie das einfachste Werkzeug verwenden sollten, das die Aufgabe gut erledigt:
- Verwenden Sie nach Möglichkeit Ansichten
- Wenn eine Ansicht nicht geeignet ist, verwenden Sie eine SQL-Funktion
- Wenn eine SQL-Funktion nicht geeignet ist, verwenden Sie PL / PgSQL.
- Wenn PL / PgSQL zu eingeschränkt oder nicht aussagekräftig genug ist, verwenden Sie PL / Perl, PL / Python, PL / V8, PL / Java oder was auch immer Sie bevorzugen
- ... und wo kein PL die Arbeit machen wird, benutze ein externes Programm und eventuell
LISTEN
und NOTIFY
um mit ihm zu reden.
Sehr häufig ist eine Ansicht ausreichend, wenn Sie denken, dass eine Funktion benötigt wird. Auch wenn dies für SELECT
die gesamte Ansicht extrem teuer ist , werden WHERE
Klauseln in der Abfrage, die auf die Ansicht verweisen, normalerweise in die Ansicht verschoben und können zu sehr unterschiedlichen Abfrageplänen führen. Ich habe oft große Leistungsverbesserungen durch das Konvertieren von SQL-Funktionen in Ansichten erhalten.
Wenn Sie feststellen, dass Sie eine Ansicht nicht verwenden können und eine SQL-Funktion in Betracht ziehen sollten, gilt Folgendes:
- Parameter, die nicht als einfache
WHERE
Klauseln ausgedrückt werden können, werden wie ein Parameter in einem WITH
Ausdruck benötigt
- Sie möchten eine Sicherheitsbarriere über eine
SECURITY DEFINER
Funktion, und die security_barrier
Ansichten in PostgreSQL 9.2 und höher sind für Ihre Anforderungen nicht ausreichend.
- Sie benötigen Parameter, die vom Optimierer nicht in Unterklauseln einer Ansicht verschoben werden und die direkter gesteuert werden sollen. oder
- Es gibt viele Parameter oder es gibt viele Wiederholungen der Parameter, daher ist es unpraktisch, die Abfrage als Ansicht zu schreiben.
Bei den meisten dieser Aufgaben funktioniert eine einfache SQL-Funktion einwandfrei und ist oft einfacher zu lesen als PL / PgSQL. Deklarierte STABLE
oder IMMUTABLE
(und nicht deklarierte STRICT
oder SECURITY DEFINER
) SQL-Funktionen können auch in die aufrufende Anweisung eingefügt werden. Dies beseitigt den Funktionsaufruf-Overhead und kann manchmal auch zu enormen Leistungsvorteilen führen, wenn eine WHERE-Bedingung in der aufrufenden Funktion vom Optimierer in die SQL-Funktion gedrückt wird. Verwenden Sie SQL-Funktionen, wenn sie für die Aufgabe ausreichen.
Die Hauptzeit, in der SQL-Funktionen den Job nicht ausführen, ist, wenn Sie viel Logik benötigen. Wenn / then / else-Operationen, die Sie nicht als CASE
Anweisungen ausdrücken können , vielfache Wiederverwendung von berechneten Ergebnissen, Aufbauen von Werten aus Chunks, Fehlerbehandlung usw., ist PL / PgSQL dann nützlich. Wählen Sie PL / PgSQL, wenn Sie SQL-Funktionen nicht verwenden können oder wenn diese nicht gut passen, wie zum Beispiel für:
- Dynamisches SQL und dynamisches DDL über die
EXECUTE
Anweisung
- Wenn Sie
RAISE
Fehler / Warnungen für die Protokolle oder Client möchten
- Wenn Sie eine Ausnahmebehandlung benötigen, können Sie Fehler mit
EXCEPTION
Blöcken abfangen und behandeln, anstatt die gesamte Transaktion bei einem Fehler zu beenden
- Komplexe bedingte Logik, die nicht
CASE ... WHEN
sehr gut passt
- Viele wiederverwendete berechnete Werte, in die Sie nicht passen,
WITH
und CTEs
- Dynamische Datensätze erstellen
- Sie müssen eine Aktion ausführen, nachdem Sie die Ergebnismenge erstellt haben
Bei allgemeinen Tabellenausdrücken (CTEs), insbesondere bei beschreibbaren CTEs WITH RECURSIVE
, verwende ich PL / PgSQL viel seltener als früher, da SQL so viel aussagekräftiger und leistungsfähiger ist. Ich benutze jetzt viel mehr Views und einfache SQL-Funktionen. Denken Sie daran, dass einfache SQL-Funktionen mehrere Anweisungen enthalten können. Die letzte Anweisung ist das Ergebnis der Funktion.