- Los grafos de propiedades de Postgres 19 son una función SQL/PGQ que declara tablas existentes como vértices y aristas, y busca patrones de relaciones fijos con
MATCH; no copia datos ni crea un motor de ejecución de grafos separado
- Los patrones de grafos se compilan como joins relacionales, por lo que usan tal cual el optimizador, los índices y las estadísticas existentes; así, los recorridos lentos se pueden analizar y optimizar igual que los joins normales
- Las tablas de dimensiones se corresponden naturalmente con vértices, y las tablas puras de join con aristas, pero conviene modelar las tablas de hechos que tienen varias claves foráneas y propiedades propias como vértices hub que representan eventos
- Una misma tabla puede declararse simultáneamente como vértice y como varias aristas con distintos alias, por lo que no hace falta crear ni almacenar tablas de aristas separadas usando las claves foráneas existentes de
results
- Postgres 19 no admite rutas de longitud variable, por lo que no es adecuado para rutas más cortas, alcanzabilidad a N saltos ni PageRank; sí es adecuado para exploraciones de longitud fija en las que se conoce de antemano la estructura relacional
Cómo leer un esquema relacional como un grafo
- En un esquema relacional normalizado, las tablas de dimensiones como
drivers, constructors y circuits contienen entidades, mientras que las tablas de hechos registran eventos como resultados de carreras o sesiones de clasificación
- Cada fila es un vértice potencial, y cada clave foránea es una arista potencial que apunta a otra fila
- Un diagrama ER corresponde a un grafo a nivel de esquema
- Las filas reales y sus relaciones de claves foráneas corresponden a un grafo a nivel de instancia
- La petición “encontrar el constructor correspondiente a cada resultado” es un recorrido de grafo que en SQL relacional se escribe como
results JOIN constructors ON ...
- SQL/PGQ no agrega un grafo nuevo como tal, sino que permite formular la pregunta en forma de grafo en lugar de enumerar joins directamente
- El enfoque de RelBench trae las tablas a pandas y construye un grafo de PyTorch en memoria, pero los grafos de propiedades de Postgres usan tal cual las relaciones entre tablas existentes dentro de la base de datos
- Los ejemplos de PyG también usan principalmente archivos planos o grafos en memoria
- El código experimentado con el dataset de Formula 1 está disponible en el repositorio de GitHub
Composición de un grafo de propiedades
CREATE PROPERTY GRAPH es un objeto declarativo con nombre que se crea sobre tablas existentes
VERTEX TABLES especifica las tablas cuyas filas se leerán como vértices
EDGE TABLES especifica las tablas cuyas filas se leerán como relaciones de conexión
- En cada tabla de vértices se definen los siguientes elementos
KEY: identificador del vértice; en la mayoría de los casos se usa la clave primaria
LABEL: nombre del tipo de vértice que se usará en MATCH
PROPERTIES: lista de columnas accesibles desde las consultas de grafo
- En cada tabla de aristas se especifican
SOURCE y DESTINATION, y ambos valores hacen referencia a la clave de un vértice
CREATE PROPERTY GRAPH no mueve ni copia datos
- Las filas permanecen en sus tablas originales
- La declaración solo define cómo leer como grafo la estructura de claves foráneas existente
- Los elementos estructurales de un grafo de propiedades son solo dos tipos: vértices y aristas
- Las etiquetas y propiedades son atributos que pertenecen a vértices o aristas
- En
psql, el Element Kind de cada elemento es vertex o edge
Consultar patrones fijos con MATCH
- Las consultas de grafo se escriben colocando un patrón
MATCH dentro de GRAPH_TABLE(...)
- El siguiente patrón representa una relación que va de driver a race pasando por result
MATCH (d IS driver)<-[IS of_driver]-(res IS result)-[IS in_race]->(ra IS race)
- La cláusula
COLUMNS especifica las columnas que la consulta de grafo devolverá al exterior
- En el
SELECT externo se puede consultar el resultado de GRAPH_TABLE(...) como si fuera una tabla normal
- Como el patrón incluye direcciones y etiquetas, la relación se lee casi como una oración, lo que facilita entender la estructura frente a un conjunto equivalente de múltiples joins
Estructura que se transforma en joins relacionales al ejecutarse
MATCH no es un motor de ejecución de grafos añadido por separado a Postgres, sino sintaxis que se compila como joins relacionales
- Al ejecutar
EXPLAIN sobre el patrón driver–result–race aparecen cuatro hash joins sobre las tablas base
- Igual que con joins escritos manualmente, usa los siguientes elementos
- El optimizador existente de Postgres
- Los índices existentes
- Las estadísticas existentes
- Si un recorrido de grafo es lento, las causas y las formas de optimizarlo son las mismas que cuando un join normal es lento
- También en
psql se pueden inspeccionar los grafos con comandos similares a los de tablas
\dG: muestra la lista de grafos de propiedades
\d f1: muestra cada vértice y arista, la tabla base, el tipo de elemento y los vértices de origen y destino de las aristas
\d+ f1: reconstruye la sentencia completa CREATE PROPERTY GRAPH, incluida la clave de arista inferida a partir de la clave primaria de la tabla de aristas
Diferencia entre claves y propiedades
- Una columna especificada como
KEY de un vértice no se convierte automáticamente en propiedad
- Si se especifica
driver_id solo como clave de vértice y luego se filtra con d.driver_id = 1, la consulta falla porque esa columna no es una propiedad consultable
- La clave identifica al vértice, pero no la expone a las consultas
- Para filtrar o devolver una columna de ID, hay que agregarla explícitamente a la lista
PROPERTIES
Restricción de rutas de longitud variable en Postgres 19
- Postgres 19 no admite cuantificadores de patrones de elementos como seguir una arista de 1 a 3 veces
ERROR: element pattern quantifier is not supported
- Para explorar dos saltos, hay que especificar dos patrones de aristas en
MATCH
- Las rutas de longitud arbitraria no pueden expresarse con la sintaxis de grafos de propiedades
- Las exploraciones de profundidad abierta deben manejarse con CTE recursivas sobre las tablas base, en cuyo caso se sale de la sintaxis de grafos de propiedades
Mapear tablas existentes a vértices y aristas
-
Las tablas de dimensiones son vértices
- Las tablas de entidades con claves primarias y atributos estables, como
drivers, constructors y circuits, se corresponden directamente con vértices
- Basta con usar la clave primaria como clave de vértice y exponer como propiedades las columnas necesarias
-
Las tablas puras de join son aristas
- Las tablas puente de muchos a muchos como
student_courses(student_id, course_id) tienen como función original conectar dos entidades, por lo que se corresponden naturalmente con aristas
- Se declara una clave foránea como vértice de origen y la otra como vértice de destino
- Como cada fila de la tabla de join ya es una relación, no se necesita una transformación de datos separada para el grafo
- En esta estructura,
students y courses son vértices, y student_courses se convierte en la arista enrolled_in
-
Las tablas de hechos son vértices de eventos
- Una fila de
results apunta a tres entidades —driver, race y constructor— y además tiene datos propios como grid, position, points y status
- Como una arista SQL/PGQ es una relación binaria con un origen y un destino, no se puede convertir toda una fila con tres claves foráneas en una sola arista
- Si la propia fila de hechos es objeto de análisis, conviene declarar esa tabla como vértice
- El vértice
results conserva el evento y sus atributos
- Aristas estrechas como
results_driver, results_race y results_constructor lo conectan con entidades externas
- Este modelo crea una estructura de hub como
driver <- result -> race, y permite detenerse en el vértice result para filtrar o consultar atributos
- Si la relación en sí es el objeto de interés, modélala como arista; si lo es una fila o evento específico con atributos propios, modélalo como vértice
- Las tablas de join representan relaciones, y las tablas de hechos representan eventos
Usar una misma tabla como vértice y arista al mismo tiempo
- La distinción “vértice o arista” se aplica a cada declaración de elemento del grafo, no a la tabla base
- Una misma tabla puede declararse en
VERTEX TABLES y EDGE TABLES con distintos alias
- Al usar
results como vértice result, se puede reutilizar la misma tabla con los siguientes alias de aristas
results AS res_driver: conecta result con driver
results AS res_race: conecta result con race
results AS res_constr: conecta result con constructor
- Cada alias de arista usa las columnas de clave primaria y claves foráneas que ya existen en
results
- No hace falta crear tablas separadas
results_driver, results_race ni results_constructor, y los alias no almacenan datos
- Una tabla de hechos con tres claves foráneas no debe declararse como una única arista con múltiples extremos, sino como tres alias de aristas, cada uno con un origen y un destino
- Este enfoque usa tres alias declarativos sobre una sola tabla base en lugar de tres tablas físicas o vistas
Conflictos de nombres y tipos de propiedades
- Si se omite
PROPERTIES, SQL/PGQ expone todas las columnas de la tabla como propiedades
- Si tanto
results como qualifying tienen una columna number, pero con tipos double precision y bigint respectivamente, se produce el siguiente error
ERROR: property "number" data type mismatch: double precision vs. bigint
- En todo el grafo, las propiedades con el mismo nombre deben tener un único tipo, por lo que chocan las columnas homónimas con tipos distintos
- Si se especifican solo las columnas necesarias en
PROPERTIES, se pueden excluir del grafo las columnas conflictivas
- Tanto el problema de que las claves no se conviertan automáticamente en propiedades como los conflictos de tipos pueden resolverse con una lista explícita de propiedades permitidas
Consultas adecuadas e inadecuadas
-
Patrones de relación fijos
- Los grafos de propiedades son adecuados para preguntas como “encuentra los objetos conectados con X mediante este patrón específico”
- En el grafo de Formula 1 se pueden escribir consultas como las siguientes
- Explorar en qué constructor corrió un driver específico
- Encontrar competidores mediante un patrón que va de driver a otro driver pasando por result, race y otro result
- Filtrar conjuntamente por condiciones de estructura y atributos, como resultados donde la posición de salida fue fuera del top 10 y el driver es italiano
- Cuando se conoce de antemano la forma de la relación y esa estructura es fija y finita, mejora la legibilidad de la sintaxis de búsqueda, filtrado y agregación
- Incluso las consultas que requieren varios self joins pueden expresarse de forma legible con un único patrón
MATCH
-
Problemas donde la ruta en sí es desconocida
- Los siguientes problemas no encajan con los grafos de propiedades de Postgres 19
- La ruta más corta entre dos drivers
- Todos los objetos alcanzables dentro de N saltos
- Exploraciones de conectividad cuya profundidad no se conoce de antemano
- Estas consultas requieren recorridos de longitud variable, por lo que deben usar CTE recursivas sobre las tablas base
- Los algoritmos de grafos como PageRank, detección de comunidades y cálculo de centralidad también son problemas distintos del pattern matching, por lo que quedan fuera del alcance de esta función
- Los grafos de propiedades encuentran objetos conectados cuando se conoce la estructura de la ruta, pero no descubren rutas cuando no se sabe por qué camino están conectados X e Y, ni calculan la importancia estructural dentro del grafo
Aspectos a evaluar antes de adoptarlo
- SQL/PGQ es una capa declarativa superpuesta sobre la estructura de claves foráneas existente y no almacena datos adicionales salvo que se elija hacerlo por separado
- Sus principales ventajas son dos
- Permite escribir recorridos de forma fija de manera más legible que con joins relacionales
- Proporciona un objeto con nombre que documenta el esquema como grafo
- La mayor limitación es que no hay rutas de longitud variable, por lo que las exploraciones profundas o abiertas deben manejarse con SQL recursivo
- Las tablas en sí no son inherentemente vértices o aristas; en cada grafo se puede decidir si leer sus filas como vértices, aristas o ambas cosas
- Si se quiere consultar patrones de grafo fijos sobre un esquema existente en Postgres 19, conviene evaluar
CREATE PROPERTY GRAPH y MATCH antes de mover los datos a una base de datos de grafos separada
- Para explorar profundidades desconocidas se necesitan CTE recursivas, pero independientemente del enfoque los datos no tienen por qué salir de Postgres
- Antes de adoptarlo en la práctica, hay que probar directamente si ofrece el rendimiento necesario
Aún no hay comentarios.