Compartir a través de


Procedimientos recomendados: indexación, AGE EXPLAIN y pruebas comparativas de carga de datos

Apache AGE compatible con Azure Database for PostgreSQL proporciona compatibilidad con el procesamiento y la consulta de grafos avanzados. Sin embargo, lograr un rendimiento óptimo de las consultas requiere una estrategia cuidadosa para la indexación y la carga de datos. En esta guía se describen algunos procedimientos recomendados basados en los resultados de pruebas comparativas recientes y la información técnica.

Indexación en Apache AGE

La indexación es fundamental para mejorar el rendimiento de las consultas, especialmente en las bases de datos de grafos.

Comportamiento predeterminado

De forma predeterminada, Apache AGE no crea índices para gráficos recién creados. Esto requiere la creación explícita de índices en función de la naturaleza de las consultas y el conjunto de datos.

Cláusula WHERE

En Apache AGE, las siguientes consultas se evalúan de forma diferente:

SELECT * FROM cypher('graph_name',
 $$
 MATCH (n:Customer {Name:'Alice'}) RETURN n
 $$)
AS (n agtype);
SELECT * FROM cypher('graph_name',
 $$
 MATCH (n:Customer) WHERE n.Name='Alice' RETURN n
 $$)
AS (n agtype);

Para aprovechar al máximo la indexación, debe comprender qué tipos de índices usan las consultas con y sin una cláusula WHERE.

EXPLAIN en Apache AGE

A diferencia de SQL estándar, la palabra clave EXPLAIN en las consultas cipher requiere un formato de consulta diferente.

SELECT * FROM cypher('graph_name',
 $$
 EXPLAIN
 MATCH (n:Customer)
 WHERE n.Name='Alice'
 RETURN n
 $$)
AS (plan text);
QUERY PLAN
--------------------------------------------------------------------------------------------------------------
Seq Scan on "Customer" n (cost=0.00..418.51 rows=43 width=32)
Filter: (agtype_access_operator(VARIADIC ARRAY[properties, '"Name"'::agtype]) = '"Alice"'::agtype)

Para ver las diferencias de los planes de consulta sin la cláusula WHERE:

SELECT * FROM cypher('graph_name',
 $$
 MATCH (n:Customer {Name:'Alice'}) RETURN n
 $$)
AS (n agtype);
QUERY PLAN
---------------------------------------------------------------
Seq Scan on "Customer" n (cost=0.00..396.56 rows=9 width=32)
Filter: (properties @> '{"Name": "Alice"}'::agtype)

Tipos de índice comunes

  • Índice BTREE: efectivo para coincidencias exactas y consultas de rango. Se recomienda usar con columnas como ID, start_id y end_id en tablas perimetrales y de vértices.
  • Índice GIN: útil para los campos JSON, lo que permite búsquedas eficaces para pares clave-valor en la columna de propiedades.

Use los siguientes comandos para crear índices para tablas perimetrales y vértices:

  • Tabla de vértices:

    CREATE INDEX ON graph_name."VLABEL" USING BTREE (id);
    CREATE INDEX ON graph_name."VLABEL" USING GIN (properties);
    
  • Tabla de Microsoft Edge:

    CREATE INDEX ON graph_name."ELABEL" USING BTREE (id);
    CREATE INDEX ON graph_name."ELABEL" USING GIN (properties);
    
    CREATE INDEX ON graph_name."ELABEL" USING BTREE (start_id);
    CREATE INDEX ON graph_name."ELABEL" USING BTREE (end_id);
    

Indexación de un valor de clave específico en las propiedades

Para las consultas de destino, se puede crear un índice BTREE más pequeño y eficaz para claves específicas dentro de la columna de propiedades:

CREATE INDEX ON graph_name.label_name USING BTREE (agtype_access_operator(VARIADIC ARRAY[properties, '"KeyName"'::agtype]));

Este enfoque evita la indexación de datos innecesarios, lo que mejora la eficacia.

Información del plan de consulta con EXPLAIN

La palabra clave EXPLAIN revela cómo las consultas usan índices. No todas las consultas usan automáticamente índices, especialmente aquellos emitidos sin una cláusula WHERE. Use EXPLAIN para comprobar el uso del índice y optimizar las consultas en consecuencia.

Observaciones comparativas

Las pruebas recientes resaltan el impacto de la indexación en el rendimiento de las consultas.

Consultas indexadas frente a no indexadas

En esta sección se describen las diferencias de rendimiento entre las consultas indexadas y no indexadas.

  • Los exámenes secuenciales superan los exámenes de índice para las consultas que recuperan tablas completas.
  • La indexación mejora significativamente el rendimiento de las consultas de combinación (por ejemplo, recuentos de relaciones).

Procedimientos recomendados de carga de datos

La carga eficaz de datos es fundamental para grandes conjuntos de datos.

La biblioteca AGEFreighter ofrece un proceso simplificado para la ingesta de datos.

Carga de datos con AGEFreighter

AGEFreighter es una biblioteca de Python diseñada para facilitar la carga de datos en Apache AGE. Admite varios formatos de datos, incluidos CSV, Avro y Parquet, y proporciona una interfaz sencilla para cargar datos en gráficos AGE.

Configuración del entorno

  • Ha creado una instancia de servidor flexible de Azure Database for PostgreSQL con AGE habilitado.
  • Se recomienda la herramienta de administración de dependencias de Python, como Poetry. Python 3.9 o posterior debe estar instalado.
  • La biblioteca AGEFreighter (AGEFreighter PyPi) debe instalarse como dependencia:
poetry add agefreighter

Uso del formato de datos CSV para pruebas comparativas

En el caso de las pruebas comparativas, he usado un archivo CSV para cargar datos en AGE. El formato CSV es ampliamente compatible y fácil de trabajar con, por lo que es una buena opción para las tareas de carga de datos.

Dado que el conjunto de datos usado consta de casos legales y relaciones entre ellos, he estructurado mi archivo CSV de entrada de la siguiente manera:

id,CaseID,start_vertex_type,end_CaseID,end_vertex_type
1,1005631,Case,5030916,Case
2,1005631,Case,5028652,Case
3,1005631,Case,996512,Case
4,1005631,Case,3413065,Case
5,1005631,Case,4912975,Case

Cada fila representa una relación entre dos casos. CaseID hace referencia al nodo de caso inicial, mientras que end_CaseID hace referencia al caso conectado.

Uso del script de carga de datos para pruebas comparativas

El siguiente script de Python se usó para cargar mi conjunto de datos en AGE. También puede hacer referencia a la sección "Uso de CSVFreighter" en AGEFreighter PyPi para ver un ejemplo diferente.

await instance.load(
 graph_name="CaseGraphFull",
 start_v_label="Case",
 start_id="CaseID",
 start_props=[],
 edge_type="REF",
 edge_props=[],
 end_v_label="Case",
 end_id="end_CaseID",
 end_props=[],
 csv_path="./cases.csv",
 use_copy=True,
 drop_graph=True,
 create_graph=True,
 progress=True,
)

Como puede ver, los graph_name y los campos del archivo CSV proporcionado se definen aquí. El parámetro use_copy=True garantiza una carga eficaz de datos. Los parámetros drop_graph=True y create_graph=True garantizan un inicio nuevo antes de cargar nuevos datos.

Otros orígenes de datos

AGEFreighter admite otros formatos como MultiCSV, Avro, Parquet, Azure Storage, etc. que se pueden adaptar en función de los requisitos de formato de datos. Puede obtener más información aquí: "AGEFreighter PyPi"

Pruebas comparativas de rendimiento de carga de datos

  • Tamaño del conjunto de datos: 725 000 casos, relaciones de 2,8 M.
  • Tiempo de carga: 83 segundos.

La carga eficaz de datos es esencial para controlar grandes conjuntos de datos de forma eficaz.

Nota:

Aunque es adecuado para archivos grandes, este proceso podría ser menos eficaz para conjuntos de datos más pequeños debido al tiempo de preparación.