F.38. postgres_fdw — acceder a datos almacenados en servidores externos de PostgreSQL #

F.38.1. Opciones de FDW de postgres_fdw
F.38.2. Funciones
F.38.3. Gestión de conexiones
F.38.4. Gestión de transacciones
F.38.5. Optimización de consultas remotas
F.38.6. Entorno de ejecución de consultas remotas
F.38.7. Compatibilidad entre versiones
F.38.8. Eventos de espera
F.38.9. Parámetros de configuración
F.38.10. Ejemplos
F.38.11. Autor

El módulo postgres_fdw proporciona el adaptador de datos externos (foreign-data wrapper) postgres_fdw, que se puede utilizar para acceder a los datos almacenados en servidores externos de PostgreSQL.

La funcionalidad proporcionada por este módulo se superpone sustancialmente con la funcionalidad del módulo anterior dblink. Pero postgres_fdw proporciona una sintaxis más transparente y compatible con los estándares para acceder a tablas remotas, y puede ofrecer un mejor rendimiento en muchos casos.

Para prepararte para el acceso remoto usando postgres_fdw:

  1. Instala la extensión postgres_fdw usando CREATE EXTENSION.

  2. Crea un objeto de servidor externo usando CREATE SERVER, para representar cada base de datos remota a la que te quieras conectar. Especifica la información de conexión, excepto user y password, como opciones del objeto de servidor.

  3. Crea un mapeo de usuario usando CREATE USER MAPPING, para cada usuario de la base de datos al que quieras permitir acceder a cada servidor externo. Especifica el nombre de usuario y la contraseña remotos que se utilizarán como opciones user y password del mapeo de usuario.

  4. Crea una tabla externa usando CREATE FOREIGN TABLE o IMPORT FOREIGN SCHEMA, para cada tabla remota a la que quieras acceder. Las columnas de la tabla externa deben coincidir con la tabla remota referenciada. Sin embargo, puedes usar nombres de tabla y/o columnas diferentes a los de la tabla remota si especificas los nombres remotos correctos como opciones del objeto de tabla externa.

Ahora solo necesitas hacer un SELECT en una tabla externa para acceder a los datos almacenados en su tabla remota subyacente. También puedes modificar la tabla remota usando INSERT, UPDATE, DELETE, COPY o TRUNCATE. (Por supuesto, el usuario remoto que hayas especificado en tu mapeo de usuario debe tener privilegios para hacer estas cosas).

Ten en cuenta que la opción ONLY especificada en SELECT, UPDATE, DELETE o TRUNCATE no tiene efecto al acceder o modificar la tabla remota.

Ten en cuenta que postgres_fdw actualmente carece de soporte para sentencias INSERT con una cláusula ON CONFLICT DO UPDATE. Sin embargo, la cláusula ON CONFLICT DO NOTHING está soportada, siempre que se omita una especificación de inferencia de índice único. Ten en cuenta también que postgres_fdw soporta el movimiento de filas provocado por sentencias UPDATE ejecutadas en tablas particionadas, pero actualmente no maneja el caso en el que una partición remota elegida para insertar una fila movida sea también una partición de destino de UPDATE que se actualizará en otro lugar del mismo comando.

En general, se recomienda que las columnas de una tabla externa se declaren con exactamente los mismos tipos de datos, y ordenaciones (collations) si corresponde, que las columnas referenciadas de la tabla remota. Aunque postgres_fdw es actualmente bastante flexible a la hora de realizar conversiones de tipos de datos cuando es necesario, pueden surgir anomalías semánticas sorprendentes cuando los tipos o las ordenaciones no coinciden, debido a que el servidor remoto interpreta las condiciones de la consulta de manera diferente al servidor local.

Ten en cuenta que una tabla externa se puede declarar con menos columnas, o con un orden de columnas diferente al que tiene su tabla remota subyacente. La coincidencia de las columnas con la tabla remota se realiza por nombre, no por posición.

F.38.1. Opciones de FDW de postgres_fdw #

F.38.1.1. Opciones de conexión #

Un servidor externo que utiliza el adaptador de datos externos postgres_fdw puede tener las mismas opciones que acepta libpq en las cadenas de conexión, como se describe en Section 32.1.2, excepto que estas opciones no están permitidas o tienen un manejo especial:

  • user, password y sslpassword (especifícalas en un mapeo de usuario en su lugar, o utiliza un archivo de servicio)

  • client_encoding (esta se establece automáticamente a partir de la codificación del servidor local)

  • application_name — esto puede aparecer en una o en ambas de una conexión y de la variable postgres_fdw.application_name. Si ambas están presentes, postgres_fdw.application_name anula la configuración de la conexión. A diferencia de libpq, postgres_fdw permite que application_name incluya secuencias de escape. Consulta postgres_fdw.application_name para obtener más detalles.

  • fallback_application_name (siempre se establece en postgres_fdw)

  • sslkey y sslcert — estas pueden aparecer en una o en ambas de una conexión y de un mapeo de usuario. Si ambas están presentes, la configuración del mapeo de usuario anula la configuración de la conexión.

Solo los superusuarios pueden crear o modificar mapeos de usuario con las configuraciones sslcert o sslkey.

Los usuarios que no sean superusuarios pueden conectarse a servidores externos utilizando autenticación por contraseña o con credenciales delegadas de GSSAPI, así que especifica la opción password para los mapeos de usuario pertenecientes a usuarios que no sean superusuarios donde se requiera autenticación por contraseña.

Un superusuario puede anular esta comprobación de forma individual para cada mapeo de usuario estableciendo la opción de mapeo de usuario password_required 'false', por ejemplo:

ALTER USER MAPPING FOR some_non_superuser SERVER loopback_nopw
OPTIONS (ADD password_required 'false');

Para evitar que los usuarios sin privilegios aprovechen los derechos de autenticación del usuario de Unix bajo el cual se ejecuta el servidor de postgres para escalar a derechos de superusuario, solo el superusuario puede establecer esta opción en un mapeo de usuario.

Se requiere cuidado para garantizar que esto no permita al usuario mapeado la capacidad de conectarse como superusuario a la base de datos mapeada según CVE-2007-3278 y CVE-2007-6601. No establezcas password_required=false en el rol public. Ten en cuenta que el usuario mapeado puede potencialmente usar cualquier certificado de cliente, .pgpass, .pg_service.conf, etc. en el directorio personal de Unix del usuario del sistema bajo el cual se ejecuta el servidor de postgres. (Para obtener detalles sobre cómo se encuentran los directorios personales, consulta Section 32.16). También pueden usar cualquier relación de confianza otorgada por modos de autenticación como la autenticación peer o ident.

F.38.1.2. Opciones de nombre de objeto #

Estas opciones se pueden usar para controlar los nombres utilizados en las sentencias SQL enviadas al servidor remoto de PostgreSQL. Estas opciones son necesarias cuando se crea una tabla externa con nombres diferentes a los de la tabla remota subyacente.

schema_name (string)

Esta opción, que se puede especificar para una tabla externa, indica el nombre del esquema que se usará para la tabla externa en el servidor remoto. Si esta opción se omite, se utiliza el nombre del esquema de la tabla externa.

table_name (string)

Esta opción, que se puede especificar para una tabla externa, indica el nombre de la tabla que se usará para la tabla externa en el servidor remoto. Si esta opción se omite, se utiliza el nombre de la tabla externa.

column_name (string)

Esta opción, que se puede especificar para una columna de una tabla externa, indica el nombre de la columna que se usará para la columna en el servidor remoto. Si esta opción se omite, se utiliza el nombre de la columna.

F.38.1.3. Opciones de estimación de costos #

postgres_fdw recupera datos remotos ejecutando consultas contra servidores remotos, por lo que idealmente el costo estimado de escanear una tabla externa debería ser el costo de hacerlo en el servidor remoto, más un costo adicional por la comunicación. La forma más confiable de obtener dicha estimación es preguntar al servidor remoto y luego agregar algo para el costo adicional — pero para consultas simples, puede no valer el costo de una consulta remota adicional para obtener una estimación de costos. Por lo tanto, postgres_fdw proporciona las siguientes opciones para controlar cómo se realiza la estimación de costos:

use_remote_estimate (boolean)

Esta opción, que se puede especificar para una tabla externa o un servidor externo, controla si postgres_fdw emite comandos EXPLAIN remotos para obtener estimaciones de costos. Una configuración para una tabla externa anula cualquier configuración para su servidor, pero solo para esa tabla. El valor predeterminado es false.

fdw_startup_cost (floating point)

Esta opción, que se puede especificar para un servidor externo, es un valor de punto flotante que se agrega al costo estimado de inicio de cualquier escaneo de tabla externa en ese servidor. Esto representa el costo adicional de establecer una conexión, analizar y planificar la consulta en el lado remoto, etc. El valor predeterminado es 100.

fdw_tuple_cost (floating point)

Esta opción, que se puede especificar para un servidor externo, es un valor de punto flotante que se utiliza como costo adicional por tupla para los escaneos de tablas externas en ese servidor. Esto representa el costo adicional de la transferencia de datos entre servidores. Puedes aumentar o disminuir este número para reflejar un retraso de red mayor o menor hacia el servidor remoto. El valor predeterminado es 0.2.

Cuando use_remote_estimate es true, postgres_fdw obtiene las estimaciones de recuento de filas y costos del servidor remoto y luego agrega fdw_startup_cost y fdw_tuple_cost a las estimaciones de costos. Cuando use_remote_estimate es false, postgres_fdw realiza una estimación local del recuento de filas y costos y luego agrega fdw_startup_cost and fdw_tuple_cost a las estimaciones de costos. Es poco probable que esta estimación local sea muy precisa a menos que estén disponibles copias locales de las estadísticas de la tabla remota. Ejecutar ANALYZE en la tabla externa es la forma de actualizar las estadísticas locales; esto realizará un escaneo de la tabla remota y luego calculará y almacenará las estadísticas tal como si la tabla fuera local. Mantener estadísticas locales puede ser una forma útil de reducir el costo de planificación por consulta para una tabla remota — pero si la tabla remota se actualiza con frecuencia, las estadísticas locales pronto quedarán obsoletas.

La siguiente opción controla cómo se comporta dicha operación ANALYZE:

analyze_sampling (string)

Esta opción, que se puede especificar para una tabla externa o un servidor externo, determina si ANALYZE en una tabla externa toma muestras de los datos en el lado remoto, o lee y transfiere todos los datos y realiza el muestreo localmente. Los valores admitidos son off, random, system, bernoulli y auto. off desactiva el muestreo remoto, por lo que todos los datos se transfieren y se muestrean localmente. random realiza un muestreo remoto utilizando la función random() para elegir las filas devueltas, mientras que system y bernoulli se basan en los métodos integrados de TABLESAMPLE con esos nombres. random funciona en todas las versiones de servidores remotos, mientras que TABLESAMPLE solo se admite desde la versión 9.5. auto (el valor predeterminado) elige automáticamente el método de muestreo recomendado; actualmente esto significa ya sea bernoulli o random según la versión del servidor remoto.

F.38.1.4. Opciones de ejecución remota #

Por defecto, solo las cláusulas WHERE que utilizan operadores y funciones integrados se considerarán para su ejecución en el servidor remoto. Las cláusulas que involucran funciones no integradas se comprueban localmente después de recuperar las filas. Si dichas funciones están disponibles en el servidor remoto y se puede confiar en que produzcan los mismos resultados que localmente, se puede mejorar el rendimiento enviando dichas cláusulas WHERE para su ejecución remota. Este comportamiento se puede controlar mediante la siguiente opción:

extensions (string)

Esta opción es una lista separada por comas de nombres de extensiones de PostgreSQL que están instaladas, en versiones compatibles, tanto en el servidor local como en el remoto. Las funciones y los operadores que son inmutables y pertenecen a una extensión de la lista se considerarán aptos para ser enviados al servidor remoto. Esta opción solo se puede especificar para servidores externos, no por tabla.

Al utilizar la opción extensions, es responsabilidad del usuario que las extensiones enumeradas existan y se comporten de manera idéntica tanto en el servidor local como en el remoto. De lo contrario, las consultas remotas pueden fallar o comportarse de manera inesperada.

fetch_size (integer)

Esta opción especifica el número de filas que postgres_fdw debe obtener en cada operación de recuperación (fetch). Se puede especificar para una tabla externa o un servidor externo. La opción especificada en una tabla anula una opción especificada para el servidor. El valor predeterminado es 100.

batch_size (integer)

Esta opción especifica el número de filas que postgres_fdw debe insertar en cada operación de inserción. Se puede especificar para una tabla externa o un servidor externo. La opción especificada en una tabla anula una opción especificada para el servidor. El valor predeterminado es 1.

Ten en cuenta que el número real de filas que postgres_fdw inserta a la vez depende del número de columnas y del valor de batch_size proporcionado. El lote se ejecuta como una sola consulta, y el protocolo libpq (que postgres_fdw utiliza para conectarse a un servidor remoto) limita el número de parámetros en una sola consulta a 65535. Cuando el número de columnas * batch_size supera el límite, el batch_size se ajustará para evitar un error.

Esta opción también se aplica cuando se copia en tablas externas. En ese caso, el número real de filas que postgres_fdw copia a la vez se determina de forma similar al caso de inserción, pero está limitado a un máximo de 1000 debido a restricciones de implementación del comando COPY.

F.38.1.5. Opciones de ejecución asíncrona #

postgres_fdw admite la ejecución asíncrona, que ejecuta múltiples partes de un nodo Append de forma concurrente en lugar de secuencial para mejorar el rendimiento. Esta ejecución se puede controlar mediante la siguiente opción:

async_capable (boolean)

Esta opción controla si postgres_fdw permite que las tablas externas se escaneen de forma concurrente para la ejecución asíncrona. Se puede especificar para una tabla externa o un servidor externo. Una opción a nivel de tabla anula una opción a nivel de servidor. El valor predeterminado es false.

Para garantizar que los datos devueltos desde un servidor externo sean consistentes, postgres_fdw solo abrirá una conexión para un servidor externo determinado y ejecutará todas las consultas contra ese servidor de forma secuencial, incluso si hay múltiples tablas externas involucradas, a menos que esas tablas estén sujetas a mapeos de usuario diferentes. En tal caso, puede ser más eficiente desactivar esta opción para eliminar el costo adicional asociado con la ejecución de consultas de forma asíncrona.

La ejecución asíncrona se aplica incluso cuando un nodo Append contiene subplan(es) ejecutados de forma síncrona, así como subplan(es) ejecutados de forma asíncrona. En tal caso, si los subplanes asíncronos son procesados usando postgres_fdw, las tuplas de los subplanes asíncronos no se devuelven hasta después de que al menos un subplan síncrono devuelva todas las tuplas, ya que ese subplan se ejecuta mientras los subplanes asíncronos esperan los resultados de las consultas asíncronas enviadas a los servidores externos. Este comportamiento podría cambiar en una versión futura.

F.38.1.6. Opciones de gestión de transacciones #

Como se describe en la sección de Gestión de Transacciones, en postgres_fdw las transacciones se gestionan creando las correspondientes transacciones remotas, y las subtransacciones se gestionan creando las correspondientes subtransacciones remotas. Cuando se involucran múltiples transacciones remotas en la transacción local actual, por defecto postgres_fdw confirma o aborta esas transacciones remotas de forma secuencial cuando la transacción local se confirma o se aborta. Cuando se involucran múltiples subtransacciones remotas en la subtransacción local actual, por defecto postgres_fdw confirma o aborta esas subtransacciones remotas de forma secuencial cuando la subtransacción local se confirma o se aborta. El rendimiento se puede mejorar con las siguientes opciones:

parallel_commit (boolean)

Esta opción controla si postgres_fdw confirma, en paralelo, las transacciones remotas abiertas en un servidor externo en una transacción local cuando la transacción local se confirma. Esta configuración también se aplica a las subtransacciones remotas y locales. Esta opción solo se puede especificar para servidores externos, no por tabla. El valor predeterminado es false.

parallel_abort (boolean)

Esta opción controla si postgres_fdw aborta, en paralelo, las transacciones remotas abiertas en un servidor externo en una transacción local cuando la transacción local se aborta. Esta configuración también se aplica a las subtransacciones remotas y locales. Esta opción solo se puede especificar para servidores externos, no por tabla. El valor predeterminado es false.

Si se involucran múltiples servidores externos con estas opciones habilitadas en una transacción local, las múltiples transacciones remotas en esos servidores externos se confirman o se abortan en paralelo a través de esos servidores externos cuando la transacción local se confirma o se aborta.

Cuando estas opciones están habilitadas, un servidor externo con muchas transacciones remotas puede experimentar un impacto negativo en el rendimiento cuando la transacción local se confirma o se aborta.

F.38.1.7. Opciones de actualización #

Por defecto, se asume que todas las tablas externas que utilizan postgres_fdw son actualizables. Esto se puede anular mediante la siguiente opción:

updatable (boolean)

Esta opción controla si postgres_fdw permite que las tablas externas se modifiquen mediante comandos INSERT, UPDATE y DELETE. Se puede especificar para una tabla externa o un servidor externo. Una opción a nivel de tabla anula una opción a nivel de servidor. El valor predeterminado es true.

Por supuesto, si la tabla remota no es de hecho actualizable, ocurriría un error de todos modos. El uso de esta opción permite principalmente que el error se lance localmente sin consultar al servidor remoto. Ten en cuenta, sin embargo, que las vistas de information_schema informarán que una tabla externa de postgres_fdw es actualizable (o no) según la configuración de esta opción, sin ninguna verificación del servidor remoto.

F.38.1.8. Opciones de vaciado (truncation) #

Por defecto, se asume que todas las tablas externas que utilizan postgres_fdw se pueden vaciar. Esto se puede anular mediante la siguiente opción:

truncatable (boolean)

Esta opción controla si postgres_fdw permite que las tablas externas se vacíen mediante el comando TRUNCATE. Se puede especificar para una tabla externa o un servidor externo. Una opción a nivel de tabla anula una opción a nivel de servidor. El valor predeterminado es true.

Por supuesto, si la tabla remota no es de hecho vaciable, ocurriría un error de todos modos. El uso de esta opción permite principalmente que el error se lance localmente sin consultar al servidor remoto.

F.38.1.9. Opciones de importación #

postgres_fdw es capaz de importar definiciones de tablas externas utilizando IMPORT FOREIGN SCHEMA. Este comando crea definiciones de tablas externas en el servidor local que coinciden con las tablas o vistas presentes en el servidor remoto. Si las tablas remotas a importar tienen columnas de tipos de datos definidos por el usuario, el servidor local debe tener tipos compatibles con los mismos nombres.

El comportamiento de importación se puede personalizar con las siguientes opciones (dadas en el comando IMPORT FOREIGN SCHEMA):

import_collate (boolean)

Esta opción controla si las opciones COLLATE de la columna se incluyen en las definiciones de las tablas externas importadas desde un servidor externo. El valor predeterminado es true. Es posible que debas desactivar esto si el servidor remoto tiene un conjunto diferente de nombres de ordenación que el servidor local, lo cual es probable que ocurra si se está ejecutando en un sistema operativo diferente. Sin embargo, si lo haces, existe un riesgo muy grave de que las ordenaciones de las columnas de la tabla importada no coincidan con los datos subyacentes, lo que resultará en un comportamiento de consulta anómalo.

Incluso cuando este parámetro se establece en true, importar columnas cuya ordenación es la predeterminada del servidor remoto puede ser arriesgado. Se importarán con COLLATE "default", lo cual seleccionará la ordenación predeterminada del servidor local, que podría ser diferente.

import_default (boolean)

Esta opción controla si las expresiones DEFAULT de la columna se incluyen en las definiciones de las tablas externas importadas desde un servidor externo. El valor predeterminado es false. Si habilitas esta opción, ten cuidado con los valores predeterminados que podrían calcularse de manera diferente en el servidor local que en el servidor remoto; nextval() es una fuente común de problemas. La importación (IMPORT) fallará por completo si una expresión predeterminada importada utiliza una función o un operador que no existe localmente.

import_generated (boolean)

Esta opción controla si las expresiones GENERATED de la columna se incluyen en las definiciones de las tablas externas importadas desde un servidor externo. El valor predeterminado es true. La importación (IMPORT) fallará por completo si una expresión generada importada utiliza una función o un operador que no existe localmente.

import_not_null (boolean)

Esta opción controla si las restricciones NOT NULL de la columna se incluyen en las definiciones de las tablas externas importadas desde un servidor externo. El valor predeterminado es true.

Note that constraints other than NOT NULL will never be imported from the remote tables. Although PostgreSQL does support check constraints on foreign tables, there is no provision for importing them automatically, because of the risk that a constraint expression could evaluate differently on the local and remote servers. Any such inconsistency in the behavior of a check constraint could lead to hard-to-detect errors in query optimization. So if you wish to import check constraints, you must do so manually, and you should verify the semantics of each one carefully. For more detail about the treatment of check constraints on foreign tables, see CREATE FOREIGN TABLE.

Tables or foreign tables which are partitions of some other table are imported only when they are explicitly specified in LIMIT TO clause. Otherwise they are automatically excluded from IMPORT FOREIGN SCHEMA. Since all data can be accessed through the partitioned table which is the root of the partitioning hierarchy, importing only partitioned tables should allow access to all the data without creating extra objects.

F.38.1.10. Opciones de gestión de conexiones #

Por defecto, todas las conexiones que postgres_fdw establece con los servidores externos se mantienen abiertas en la sesión local para su reutilización.

keep_connections (boolean) #

Esta opción controla si postgres_fdw mantiene abiertas las conexiones al servidor externo para que las consultas posteriores puedan reutilizarlas. Solo se puede especificar para un servidor externo. El valor predeterminado es on. Si se establece en off, todas las conexiones a este servidor externo se descartarán al final de cada transacción.

use_scram_passthrough (boolean) #

Esta opción controla si postgres_fdw utilizará la autenticación de paso de SCRAM (SCRAM pass-through authentication) para conectarse al servidor externo. Con la autenticación de paso de SCRAM, postgres_fdw utiliza secretos con hash SCRAM en lugar de contraseñas de usuario en texto plano para conectarse al servidor remoto. Esto evita almacenar contraseñas de usuario en texto plano en los catálogos del sistema de PostgreSQL.

Para utilizar la autenticación de paso de SCRAM:

  • El servidor remoto debe solicitar el método de autenticación scram-sha-256; de lo contrario, la conexión fallará.

  • El servidor remoto puede ser de cualquier versión de PostgreSQL que admita SCRAM. El soporte para use_scram_passthrough solo se requiere en el lado del cliente (lado FDW).

  • No se utiliza la contraseña del mapeo de usuario.

  • El servidor que ejecuta postgres_fdw y el servidor remoto deben tener secretos SCRAM idénticos (contraseñas cifradas) para el usuario que se utiliza en postgres_fdw para autenticarse en el servidor externo (misma sal e iteraciones, no simplemente la misma contraseña).

    Como corolario, si se van a realizar conexiones FDW a múltiples hosts, por ejemplo para tablas externas particionadas/sharding, entonces todos los hosts deben tener secretos SCRAM idénticos para los usuarios involucrados.

  • La sesión actual en la instancia de PostgreSQL que realiza las conexiones FDW salientes también debe utilizar autenticación SCRAM para su conexión de cliente entrante. (De ahí la autenticación de paso: se debe usar SCRAM tanto al entrar como al salir). Este es un requisito técnico del protocolo SCRAM.

F.38.2. Funciones #

postgres_fdw_get_connections( IN check_conn boolean DEFAULT false, OUT server_name text, OUT user_name text, OUT valid boolean, OUT used_in_xact boolean, OUT closed boolean, OUT remote_backend_pid int4) returns setof record

Esta función devuelve información sobre todas las conexiones abiertas que postgres_fdw ha establecido desde la sesión local a los servidores externos. Si no hay conexiones abiertas, no se devuelven registros.

Si check_conn se establece en true, la función comprueba el estado de cada conexión y muestra el resultado en la columna closed. Esta característica está disponible actualmente solo en sistemas que admiten la extensión no estándar POLLRDHUP para la llamada al sistema poll, incluido Linux. Esto es útil para comprobar si todas las conexiones utilizadas dentro de una transacción siguen abiertas. Si alguna conexión se cierra, la transacción no se puede confirmar con éxito, por lo que es mejor revertirla tan pronto como se detecte una conexión cerrada, en lugar de continuar hasta el final. Los usuarios pueden revertir la transacción inmediatamente si la función informa de conexiones donde tanto used_in_xact como closed son true.

Ejemplo de uso de la función:

postgres=# SELECT * FROM postgres_fdw_get_connections(true);
 server_name | user_name | valid | used_in_xact | closed | remote_backend_pid
-------------+-----------+-------+--------------+-----------------------------
 loopback1   | postgres  | t     | t            | f      |            1353340
 loopback2   | public    | t     | t            | f      |            1353120
 loopback3   |           | f     | t            | f      |            1353156

Las columnas de salida se describen en Table F.28.

Table F.28. Columnas de salida de postgres_fdw_get_connections

ColumnaTipoDescripción
server_nametext El nombre del servidor externo de esta conexión. Si el servidor se elimina pero la conexión permanece abierta (es decir, marcada como inválida), esto será NULL.
user_nametext Nombre del usuario local mapeado al servidor externo de esta conexión, o public si se utiliza un mapeo público. Si el mapeo de usuario se elimina pero la conexión permanece abierta (es decir, marcada como inválida), esto será NULL.
validboolean Falso si esta conexión no es válida, lo que significa que se utiliza en la transacción actual, pero su servidor externo o mapeo de usuario ha sido modificado o eliminado. La conexión no válida se cerrará al final de la transacción. En caso contrario, se devuelve True.
used_in_xactboolean True si esta conexión se utiliza en la transacción actual.
closedboolean True si esta conexión está cerrada, false en caso contrario. Se devuelve NULL si check_conn se establece en false o si la comprobación del estado de la conexión no está disponible en esta plataforma.
remote_backend_pidint4 ID de proceso del backend remoto, en el servidor externo, que maneja la conexión. Si el backend remoto se termina y la conexión se cierra (con closed establecido en true), esto todavía muestra el ID de proceso del backend terminado.

postgres_fdw_disconnect(server_name text) returns boolean

Esta función descarta las conexiones abiertas que están establecidas por postgres_fdw desde la sesión local al servidor externo con el nombre dado. Ten en cuenta que puede haber múltiples conexiones al servidor dado utilizando diferentes mapeos de usuario. Si las conexiones se utilizan en la transacción local actual, no se desconectan y se informan mensajes de advertencia. Esta función devuelve true si desconecta al menos una conexión, de lo contrario false. Si no se encuentra ningún servidor externo con el nombre dado, se informa de un error. Ejemplo de uso de la función:

postgres=# SELECT postgres_fdw_disconnect('loopback1');
 postgres_fdw_disconnect
-------------------------
 t

postgres_fdw_disconnect_all() returns boolean

Esta función descarta todas las conexiones abiertas que están establecidas por postgres_fdw desde la sesión local a los servidores externos. Si las conexiones se utilizan en la transacción local actual, no se desconectan y se informan mensajes de advertencia. Esta función devuelve true si desconecta al menos una conexión, de lo contrario false. Ejemplo de uso de la función:

postgres=# SELECT postgres_fdw_disconnect_all();
 postgres_fdw_disconnect_all
-----------------------------
 t

F.38.3. Gestión de conexiones #

postgres_fdw establece una conexión a un servidor externo durante la primera consulta que utiliza una tabla externa asociada con el servidor externo. Por defecto, esta conexión se mantiene y se reutiliza para consultas posteriores en la misma sesión. Este comportamiento se puede controlar mediante la opción keep_connections para un servidor externo. Si se utilizan múltiples identidades de usuario (mapeos de usuario) para acceder al servidor externo, se establece una conexión para cada mapeo de usuario.

Al cambiar la definición o eliminar un servidor externo o un mapeo de usuario, se cierran las conexiones asociadas. Pero ten en cuenta que si alguna conexión se está utilizando en la transacción local actual, se mantiene hasta el final de la transacción. Las conexiones cerradas se volverán a establecer cuando sean necesarias por futuras consultas que utilicen una tabla externa.

Una vez establecida una conexión a un servidor externo, por defecto se mantiene hasta que finaliza la sesión local o la correspondiente sesión remota. Para desconectar una conexión explícitamente, se puede desactivar la opción keep_connections para un servidor externo, o se pueden usar las funciones postgres_fdw_disconnect y postgres_fdw_disconnect_all. Por ejemplo, estas son útiles para cerrar conexiones que ya no son necesarias, liberando así conexiones en el servidor externo.

F.38.4. Gestión de transacciones #

Durante una consulta que hace referencia a cualquier tabla remota en un servidor externo, postgres_fdw abre una transacción en el servidor remoto si no hay una ya abierta correspondiente a la transacción local actual. La transacción remota se confirma o se aborta cuando la transacción local se confirma o se aborta. Los puntos de salvaguarda (savepoints) se gestionan de manera similar mediante la creación de los correspondientes puntos de salvaguarda remotos.

La transacción remota utiliza el nivel de aislamiento SERIALIZABLE cuando la transacción local tiene el nivel de aislamiento SERIALIZABLE; de lo contrario, utiliza el nivel de aislamiento REPEATABLE READ. Esta elección garantiza que si una consulta realiza múltiples escaneos de tablas en el servidor remoto, obtendrá resultados consistentes con la instantánea (snapshot-consistent) para todos los escaneos. Una consecuencia es que las consultas sucesivas dentro de una sola transacción verán los mismos datos del servidor remoto, incluso si se están produciendo actualizaciones concurrentes en el servidor remoto debido a otras actividades. Ese comportamiento se esperaría de todos modos si la transacción local utiliza el nivel de aislamiento SERIALIZABLE o REPEATABLE READ, pero podría resultar sorprendente para una transacción local READ COMMITTED. Una versión futura de PostgreSQL podría modificar estas reglas.

Ten en cuenta que actualmente postgres_fdw no admite la preparación de la transacción remota para una confirmación en dos fases (two-phase commit).

F.38.5. Optimización de consultas remotas #

postgres_fdw intenta optimizar las consultas remotas para reducir la cantidad de datos transferidos desde los servidores externos. Esto se hace enviando las cláusulas WHERE de la consulta al servidor remoto para su ejecución, y no recuperando las columnas de la tabla que no son necesarias para la consulta actual. Para reducir el riesgo de una ejecución incorrecta de las consultas, las cláusulas WHERE no se envían al servidor remoto a menos que utilicen únicamente tipos de datos, operadores y funciones que sean integrados o pertenezcan a una extensión que figure en la opción extensions del servidor externo. Los operadores y funciones en tales cláusulas también deben ser IMMUTABLE. Para una consulta UPDATE o DELETE, postgres_fdw intenta optimizar la ejecución de la consulta enviando toda la consulta al servidor remoto si no hay cláusulas WHERE de la consulta que no se puedan enviar al servidor remoto, no hay uniones (joins) locales para la consulta, no hay disparadores (triggers) locales a nivel de fila BEFORE o AFTER o columnas generadas almacenadas en la tabla de destino, y no hay restricciones CHECK OPTION de las vistas principales. En UPDATE, las expresiones a asignar a las columnas de destino deben usar únicamente tipos de datos integrados, operadores IMMUTABLE o funciones IMMUTABLE, para reducir el riesgo de una ejecución incorrecta de la consulta.

Cuando postgres_fdw encuentra una unión (join) entre tablas externas en el mismo servidor externo, envía toda la unión al servidor externo, a menos que por alguna razón crea que será más eficiente recuperar las filas de cada tabla individualmente, o a menos que las referencias de tabla involucradas estén sujetas a mapeos de usuario diferentes. Al enviar las cláusulas JOIN, toma las mismas precauciones mencionadas anteriormente para las cláusulas WHERE.

La consulta que realmente se envía al servidor remoto para su ejecución se puede examinar utilizando EXPLAIN VERBOSE.

F.38.6. Entorno de ejecución de consultas remotas #

En las sesiones remotas abiertas por postgres_fdw, el parámetro search_path se establece únicamente en pg_catalog, de modo que solo los objetos integrados son visibles sin calificación de esquema. Esto no es un problema para las consultas generadas por la propia herramienta postgres_fdw, porque siempre proporciona dicha calificación. Sin embargo, esto puede representar un riesgo para las funciones que se ejecutan en el servidor remoto a través de disparadores o reglas en tablas remotas. Por ejemplo, si una tabla remota es en realidad una vista, cualquier función utilizada en esa vista se ejecutará con la ruta de búsqueda restringida. Se recomienda calificar con el esquema todos los nombres en dichas funciones, o bien adjuntar opciones SET search_path (consulta CREATE FUNCTION) a dichas funciones para establecer el entorno de ruta de búsqueda esperado.

postgres_fdw del mismo modo establece la configuración de la sesión remota para varios parámetros:

Es menos probable que estos parámetros sean problemáticos que search_path, pero se pueden manejar con las opciones SET de la función si surge la necesidad.

No se recomienda que sobrescribas este comportamiento cambiando la configuración a nivel de sesión de estos parámetros; es probable que eso cause un mal funcionamiento de postgres_fdw.

F.38.7. Compatibilidad entre versiones #

postgres_fdw se puede utilizar con servidores remotos desde la versión 8.3 de PostgreSQL. La capacidad de solo lectura está disponible hasta la versión 8.1.

Sin embargo, una limitación es que postgres_fdw generalmente asume que las funciones y operadores integrados inmutables son seguros de enviar al servidor remoto para su ejecución, si aparecen en una cláusula WHERE de una tabla externa. Por lo tanto, una función integrada que se agregó desde el lanzamiento del servidor remoto podría enviarse a él para su ejecución, lo que provocaría un error del tipo la función no existe o similar. Este tipo de fallo se puede solucionar reescribiendo la consulta, por ejemplo, envolviendo la referencia de la tabla externa en una subconsulta SELECT con OFFSET 0 como una barrera de optimización y colocando la función u operador problemático fuera de la subconsulta SELECT.

Otra limitación es que al ejecutar sentencias INSERT con una cláusula ON CONFLICT DO NOTHING en una tabla externa, el servidor remoto debe estar ejecutando PostgreSQL 9.5 o posterior, ya que las versiones anteriores no admiten esta característica.

F.38.8. Eventos de espera #

postgres_fdw puede informar los siguientes eventos de espera bajo el tipo de evento de espera Extension:

PostgresFdwCleanupResult

Esperando el aborto de la transacción en el servidor remoto.

PostgresFdwConnect

Esperando establecer una conexión con un servidor remoto.

PostgresFdwGetResult

Esperando recibir los resultados de una consulta de un servidor remoto.

F.38.9. Parámetros de configuración #

postgres_fdw.application_name (string) #

Especifica un valor para el parámetro de configuración application_name utilizado cuando postgres_fdw establece una conexión con un servidor externo. Esto anula la opción application_name del objeto de servidor. Ten en cuenta que el cambio de este parámetro no afecta a ninguna de las conexiones existentes hasta que se vuelvan a establecer.

postgres_fdw.application_name puede ser cualquier cadena de cualquier longitud y contener incluso caracteres no ASCII. Sin embargo, cuando se pasa y se utiliza como application_name en un servidor externo, ten en cuenta que se truncará a menos de NAMEDATALEN caracteres. Cualquier carácter que no sea ASCII imprimible se reemplaza con escapes hexadecimales de estilo C. Consulta application_name para obtener más detalles.

Los caracteres % inician secuencias de escape que se reemplazan con información de estado como se detalla a continuación. Los escapes no reconocidos se ignoran. Otros caracteres se copian directamente al nombre de la aplicación. Ten en cuenta que no está permitido especificar un signo más/menos o un literal numérico después del % y antes de la opción para fines de alineación y relleno.

EscapeEfecto
%aNombre de la aplicación en el servidor local
%c ID de sesión en el servidor local (consulta log_line_prefix para obtener más detalles)
%C Nombre del clúster en el servidor local (consulta cluster_name para obtener más detalles)
%uNombre de usuario en el servidor local
%dNombre de la base de datos en el servidor local
%pID de proceso del backend en el servidor local
%%Carácter % literal

Por ejemplo, supongamos que el usuario local_user establece una conexión desde la base de datos local_db a foreign_db como el usuario foreign_user, la configuración 'db=%d, user=%u' se reemplaza por 'db=local_db, user=local_user'.

F.38.10. Ejemplos #

Aquí tienes un ejemplo de cómo crear una tabla externa con postgres_fdw. Primero instala la extensión:

CREATE EXTENSION postgres_fdw;

Luego crea un servidor externo utilizando CREATE SERVER. En este ejemplo queremos conectarnos a un servidor de PostgreSQL en el host 192.83.123.89 escuchando en el puerto 5432. La base de datos a la que se realiza la conexión se llama foreign_db en el servidor remoto:

CREATE SERVER foreign_server
        FOREIGN DATA WRAPPER postgres_fdw
        OPTIONS (host '192.83.123.89', port '5432', dbname 'foreign_db');

También se necesita un mapeo de usuario, definido con CREATE USER MAPPING, para identificar el rol que se utilizará en el servidor remoto:

CREATE USER MAPPING FOR local_user
        SERVER foreign_server
        OPTIONS (user 'foreign_user', password 'password');

Ahora es posible crear una tabla externa con CREATE FOREIGN TABLE. En este ejemplo queremos acceder a la tabla llamada some_schema.some_table en el servidor remoto. El nombre local para ella será foreign_table:

CREATE FOREIGN TABLE foreign_table (
        id integer NOT NULL,
        data text
)
        SERVER foreign_server
        OPTIONS (schema_name 'some_schema', table_name 'some_table');

Es fundamental que los tipos de datos y otras propiedades de las columnas declaradas en CREATE FOREIGN TABLE coincidan con la tabla remota real. Los nombres de las columnas también deben coincidir, a menos que adjuntes opciones column_name a las columnas individuales para mostrar cómo se llaman en la tabla remota. En muchos casos, el uso de IMPORT FOREIGN SCHEMA es preferible a construir definiciones de tablas externas manualmente.

F.38.11. Autor #

Shigeru Hanada