你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

最佳做法:索引编制、AGE EXPLAIN 和数据加载基准

Azure Database for PostgreSQL 支持的 Apache AGE 为高级图形处理和查询提供支持。 但是,实现最佳的查询性能需要一个深思熟虑的策略来编制索引和数据加载。 本指南概述了基于最近基准测试结果和技术见解的一些最佳做法。

Apache AGE 中的索引

索引对于提高查询性能至关重要,尤其是在图形数据库中。

默认行为

默认情况下,Apache AGE 不会为新创建的图形创建索引。 这需要根据查询和数据集的性质显式创建索引。

WHERE 子句

在 Apache AGE 中,以下查询的计算方式不同:

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);

若要充分利用索引,必须了解有和没有 WHERE 子句的查询使用的索引类型。

Apache AGE 中的 EXPLAIN

与标准 SQL 不同,密码查询中的 EXPLAIN 关键字需要不同的查询格式。

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)

若要查看不带 WHERE 子句的 SQL 查询计划的区别,

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)

常见索引类型

  • BTREE 索引:适用于完全匹配和范围查询。 建议用于边缘和顶点表中的 ID、start_id 和 end_id 等列。
  • GIN 索引:适用于 JSON 字段,从而在属性列中有效搜索键值对。

使用以下命令为顶点表和边缘表创建索引:

  • 顶点表:

    CREATE INDEX ON graph_name."VLABEL" USING BTREE (id);
    CREATE INDEX ON graph_name."VLABEL" USING GIN (properties);
    
  • 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);
    

在属性中为特定键值编制索引

对于目标查询,可以为属性列中的特定键创建更小、更高效的 BTREE 索引:

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

此方法可避免为不必要的数据编制索引,从而提高效率。

使用 EXPLAIN 查询计划见解

EXPLAIN 关键字揭示了查询如何使用索引。 并非所有查询都会自动使用索引,特别是那些没有 WHERE 子句的查询。 使用 EXPLAIN 验证索引使用情况并相应地优化查询。

基准观察

最近的测试突出显示了索引对查询性能的影响。

索引查询与非索引查询

本部分讨论索引查询和非索引查询之间的性能差异。

  • 在需要检索整个表的查询中,顺序扫描优于索引扫描。
  • 索引极大地提高了联接查询(例如关系计数)的性能。

数据加载最佳做法

高效的数据加载对于大型数据集至关重要。

AGEFreighter 库提供简化的数据引入过程。

使用 AGEFreighter 加载数据

AGEFreighter 是一个 Python 库,旨在促进将数据加载到 Apache AGE 中。 它支持各种数据格式,包括 CSV、Avro 和 Parquet,并提供一个简单的接口,用于将数据加载到 AGE 图形中。

环境设置

  • 创建了启用了 AGE 的 Azure Database for PostgreSQL 灵活服务器。
  • 建议使用 Python 依赖项管理工具(如诗歌)。 必须安装 Python 3.9 或更高版本。
  • AGEFreighter 库(AGEFreighter PyPi)必须安装为依赖项:
poetry add agefreighter

使用 CSV 数据格式进行基准测试

对于基准测试,我使用 CSV 文件将数据加载到 AGE 中。 CSV 格式受到广泛支持且易于使用,因此非常适合数据加载任务。

由于使用的数据集由法律案例和它们之间的关系组成,因此我按如下所示构建了输入 CSV 文件:

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

每行表示两个事例之间的关系。 CaseID 是指起始案例节点,而 end_CaseID 指连接的案例。

使用数据加载脚本进行基准测试

以下 Python 脚本用于将数据集加载到 AGE 中。 还可以参阅 AGEFreighter PyPi 中的“CSVFreighter 用法”部分,了解其他示例。

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,
)

如你所见,此处定义了提供的 csv 文件中的 graph_name 和字段。 use_copy=True 参数可确保高效加载数据。 drop_graph=True 和 create_graph=True 参数确保在加载新数据之前重新开始。

其他数据源

AGEFreighter 支持其他格式,例如 MultiCSV、Avro、Parquet、Azure 存储等,可根据数据格式要求进行调整。 可以在此处获取详细信息: “AGEFreighter PyPi”

数据加载性能基准

  • 数据集大小:725K 个事例,2.8M 关系。
  • 加载时间:83 秒。

高效数据加载对于有效处理大型数据集至关重要。

注释

虽然适用于大型文件,但由于准备时间,此过程对较小的数据集可能不太有效。