Estrictamente hablando, el término "procedimientos almacenados" apunta a procedimientos SQL en Postgres, introducido con Postgres 11. Relacionado:
También hay funciones que hacen casi, pero no exactamente lo mismo, y que han estado allí desde el principio.
Las funciones con LANGUAGE sql
son básicamente archivos por lotes con comandos SQL simples en un contenedor de funciones (y, por lo tanto, atómico, siempre se ejecutan dentro de una sola transacción) que aceptan parámetros. Todas las declaraciones en una función SQL se planifican a la vez , lo que es sutilmente diferente de ejecutar una declaración después de la otra y puede afectar el orden en que se toman los bloqueos.
Para cualquier otra cosa, el lenguaje más maduro es PL / pgSQL ( LANGUAGE plpgsql
). Funciona bien y se ha mejorado con cada lanzamiento en la última década, pero sirve mejor como pegamento para los comandos SQL. No está destinado a cálculos pesados (que no sean con comandos SQL).
Las funciones PL / pgSQL ejecutan consultas como declaraciones preparadas . Reutilizar los planes de consulta en caché reduce algunos gastos generales de planificación y los hace un poco más rápidos que las declaraciones SQL equivalentes, lo que puede ser un efecto notable dependiendo de las circunstancias. También puede tener efectos secundarios como en esta pregunta relacionada:
Esto conlleva las ventajas y desventajas de las declaraciones preparadas, como se explica en el manual . Para consultas en tablas de datos con distribución irregular y parámetros variables SQL dinámico con EXECUTE
puede funcionar mejor cuando la ganancia de un plan de ejecución optimizado para el parámetro determinado (s) es mayor que el costo de la replanificación.
Dado que los planes de ejecución genéricos de Postgres 9.2 todavía se almacenan en caché para la sesión pero, citando el manual :
Esto ocurre inmediatamente para declaraciones preparadas sin parámetros; de lo contrario, ocurre solo después de que cinco o más ejecuciones producen planes cuyo costo promedio estimado (incluida la sobrecarga de planificación) es más costoso que el costo estimado del plan genérico.
Obtenemos lo mejor de ambos mundos la mayor parte del tiempo (menos algunos gastos generales adicionales) sin (ab) usar EXECUTE
. Detalles en Novedades de PostgreSQL 9.2 de PostgreSQL Wiki .
Postgres 12 presenta la variable de servidorplan_cache_mode
adicional para forzar planes genéricos o personalizados. Para casos especiales, usar con cuidado.
Puede ganar en grande con las funciones del lado del servidor que evitan los viajes de ida y vuelta adicionales al servidor de la base de datos desde su aplicación. Haga que el servidor ejecute tanto como sea posible a la vez y solo devuelva un resultado bien definido.
Evite anidar funciones complejas, especialmente funciones de tabla ( RETURNING SETOF record
o TABLE (...)
). Las funciones son cajas negras que se presentan como barreras de optimización para el planificador de consultas. Se optimizan por separado, no en el contexto de la consulta externa, lo que simplifica la planificación, pero puede dar como resultado planes menos que perfectos. Además, el costo y el tamaño del resultado de las funciones no se pueden predecir de manera confiable.
La excepción a esta regla son las funciones simples de SQL ( LANGUAGE sql
), que pueden " integrarse " , si se cumplen algunas condiciones previas . Lea más sobre cómo funciona el planificador de consultas en esta presentación de Neil Conway (material avanzado).
En PostgreSQL, una función siempre se ejecuta automáticamente dentro de una sola transacción . Todo tiene éxito o nada. Si ocurre una excepción, todo se revierte. Pero hay un manejo de errores ...
Esa es también la razón por la cual las funciones no son exactamente "procedimientos almacenados" (aunque ese término se usa a veces, de manera engañosa). Algunos comandos gusta VACUUM
, CREATE INDEX CONCURRENTLY
o CREATE DATABASE
no se puede ejecutar dentro de un bloque de transacción, por lo que no están permitidos en funciones. (Ni en los procedimientos SQL, todavía, a partir de Postgres 11. Eso podría agregarse más adelante).
He escrito miles de funciones plpgsql a lo largo de los años.