The Register publicó el viernes una pieza sobre PostgreSQL 19 y las consultas de grafo estandarizadas, y en cosa de un día los agregadores lo habían reducido a lo de siempre: Postgres ya es una base de datos de grafos, ve borrando Neo4j.
Bueno. Más o menos. La funcionalidad existe y me gusta más de lo que esperaba. Pero su forma es casi la contraria de lo que sugiere ese titular, y la diferencia importa, porque cambia para qué la usarías de verdad.
Primero, situación: la 19 no ha salido. La beta 3 aterrizó el 13 de agosto, todavía no hay release candidate, y la cadencia habitual del proyecto —septiembre u octubre— deja la GA a unas semanas vista. El feature freeze ya pasó, eso sí, así que lo que hay dentro es lo que sale.
Qué ha entrado exactamente
SQL/PGQ —Property Graph Queries— es parte de SQL:2023, ISO/IEC 9075-16 si quieres sonar severo en una reunión. Peter Eisentraut lo commiteó el 16 de marzo junto a Ashutosh Bapat, cerrando una serie de parches que llevaba años arrastrándose por commitfests.
Declaras un grafo encima de tablas que ya tienes:
CREATE PROPERTY GRAPH social
VERTEX TABLES (people, posts)
EDGE TABLES (
follows SOURCE KEY (follower_id) REFERENCES people (id)
DESTINATION KEY (followee_id) REFERENCES people (id)
);
Y luego lo consultas con el ASCII art:
SELECT * FROM GRAPH_TABLE (social
MATCH (a IS people) -[f IS follows]-> (b IS people)
WHERE a.name = 'ada'
COLUMNS (b.name AS seguido)
);
El -[f]-> es una arista dirigida. Las etiquetas que van tras IS se refieren a etiquetas del grafo, no a nombres de tabla, lo cual es más útil de lo que parece: el grafo puede llamarlo person mientras la tabla de debajo sigue llamándose tbl_people_v2_final.
Y aquí viene lo que se salta todo resumen. Un grafo de propiedades es un relkind nuevo, RELKIND_PROPGRAPH, y se comporta como una vista. Es metadatos. No hay almacenamiento de grafo, no hay estructura de adyacencia, no se copia nada, no se migra nada. El patrón se reescribe a joins normales en el rewriter, antes de que el planner sepa siquiera que había un grafo por medio. El EXPLAIN te enseña hash joins, igual que siempre.
Así que lo de «Postgres ya es una base de datos de grafos» falla justo en lo único que importa: no ha cambiado nada de cómo están tus datos en disco. Lo que te han dado es sintaxis.
Que sea solo sintaxis es la buena noticia
Y no lo digo con desprecio. La sintaxis es un entregable de verdad.
La consulta de arriba, escrita a mano, es un join de dos tablas y no pasa nada. Ahora hazlo con cuatro saltos. Acabas con la misma tabla aliasada cinco veces, una columna de ON que son todos idénticos a simple vista, y un punto donde escribiste follower_id queriendo poner followee_id. Y la consulta no falla: devuelve calladamente la gente equivocada. Ese bug lo ha desplegado todo el mundo. Yo lo he desplegado contra una tabla de nueve filas y aún así tardé veinte minutos en encontrarlo.
La sintaxis de patrones hace la dirección visual. El -[f]-> apunta a algún sitio. Ves cuándo la flecha va del revés. Eso no es poca cosa cuando la alternativa es leer nombres de columna dentro de un WHERE a las seis de la tarde.
Y hay un beneficio más silencioso. CREATE PROPERTY GRAPH se niega a ejecutarse si tus tablas de vértices no tienen clave primaria, y la inferencia de aristas por defecto quiere claves foráneas. O sea que, antes de ahorrarte una sola línea de SQL, lo primero que hace esta funcionalidad es negarse a trabajar sobre un esquema donde nadie se molestó en declarar las restricciones. Y eso me hace gracia de verdad. Es una funcionalidad de grafos que empieza auditándote la higiene relacional.
Ahora, la parte en la que el titular miente
Todos los patrones de PostgreSQL 19 son de profundidad fija.
No puedes escribir un cuantificador. Ni *, ni +, ni {1,5} colgando de una arista. Cada salto se escribe a mano, explícitamente, en el patrón. Los caminos de longitud variable son «una futura versión», que en años Postgres significa no lo metas en una hoja de ruta.
Párate a ver qué se lleva eso por delante. Nada de cierre transitivo. Nada de camino más corto. Nada de ¿existe alguna ruta entre estas dos cuentas?. Nada de todo lo que cuelga de este nodo cuando no sabes la profundidad de antemano, que es otra forma de decir: nada de árboles. ¿Quieres algo de eso? Vuelves a WITH RECURSIVE, exactamente donde estabas en la 18, exactamente donde estabas en la 12.
Eso no es una arista áspera que se lima. Es literalmente el motivo por el que la gente se va a una base de datos de grafos. Nadie en la historia de la informática ha migrado a Neo4j porque los joins de dos tablas fueran difíciles. Migran porque en el salto siete la CTE recursiva empieza a tardar once segundos, o porque se han cansado de escribir el recorrido a mano y quieren que lo lleve el motor.
Así que PostgreSQL 19 trae la ergonomía de las consultas de grafo sin los algoritmos. Es buena notación para el caso fácil. El caso fácil ya era fácil.
Sigue mereciendo la pena. Solo que la expectativa honesta es «joins más legibles», no «podemos jubilar el servicio de grafos». Si un artículo te dice lo contrario, comprueba si tiene un solo ejemplo con más de tres saltos. Casi ninguno lo tiene. El repaso de depesz es de los pocos que no lo sobrevende.
Dónde lo usaría yo
En cualquier sitio donde tengas una relación que no paras de explicarle a la gente.
El blog que estás leyendo empareja sus entradas en español e inglés con una clave compartida, para que los hreflang salgan bien. Eso es un grafo. Dos nodos y una arista. Está modelado como una columna de texto y funciona perfectamente, pero «estas dos filas son el mismo artículo en idiomas distintos» es una frase que ya he escrito en tres comentarios de código distintos, porque el nombre de la columna no lo dice y el esquema no opina al respecto. Un grafo de propiedades es un sitio donde dejar esa frase de forma que la base de datos también la lea.
Ese es el caso de uso. No la escala. Documentación con dientes.
El resto de la 19, que es la mejor parte
Las consultas de grafo se han llevado los titulares y son lo menos importante de esta versión.
REPACK entra en el core, con una variante CONCURRENTLY que mantiene la tabla legible y escribible mientras construye el heap nuevo. Es pg_repack volviendo por fin del frío tras una década como la extensión que todo el mundo instala y nadie escribe en el runbook.
El autovacuum se paraleliza: autovacuum_max_parallel_workers, ajustes por tabla y un sistema de puntuación que decide a qué tablas atender primero. Los valores por defecto son conservadores, así que no hace nada hasta que se lo pidas, lo cual es lo correcto y también significa que se te va a olvidar.
pg_plan_advice te deja fijar decisiones del planner. Cualquier DBA que haya deseado hints en Postgres va a tener sentimientos encontrados al verlos llegar como extensión del core, de un proyecto que se ha pasado veinte años explicando con paciencia por qué los hints son mala idea.
Y el JIT viene desactivado por defecto. El motivo declarado es que la activación por coste resultó poco fiable en uso general. Yo llevo apagándolo en producción desde la 12; casi todo el mundo que conozco lleva apagándolo en producción desde la 12. Da gusto ver a un proyecto escribir la heurística estaba mal en vez de dejarla puesta y que cada cual lo descubra por su cuenta con una consulta analítica misteriosamente lenta cada trimestre.
Una trampa que conviene llevar en la cabeza: default_toast_compression pasa a lz4, pero nada recomprime lo que ya estaba. Los chunks viejos en pglz siguen en pglz hasta que esas filas se actualicen, y ninguna de las dos variantes de REPACK los reescribe. Así que el benchmark que hagas la semana siguiente a actualizar está midiendo una mezcla, y cuando salga deslúcido, ya sabes por qué.
En fin
Postgres 19 ha ganado una notación estándar bastante maja para algo que ya hacías con joins, y no ha ganado lo que hace que las bases de datos de grafos sean un producto aparte. Las dos mitades son ciertas, e internet ha decidido llevarse solo la primera.
¿Actualizar? Sí, pero por REPACK y por el autovacuum paralelo. Y luego, alguna tarde en la que estés mirando el quinto self-join de una consulta sobre quién sigue a quién, escribe un CREATE PROPERTY GRAPH encima y comprueba si la flecha apuntaba hacia donde tú creías.
Eso sí: no canceles el contrato de Neo4j por un titular. Cuenta los saltos primero.
Comentarios