一、基础知识介绍(一)图数据库图数据库以顶点 (Vertex / Node)、边 (Edge / Relationship) 与属性 (Property) 三种元素表达事物及其关联关系。顶点对应实体, 边对应实体之间的关系, 属性以键值对形式附着在顶点或边上。相较关系数据库, 图数据库把 关系 提升为存储层的一等公民, 对多对多、深度关联的查询尤为高效。在工业界, 属性图模型 (Property Graph Model) 已成为 Neo4j、TuGraph、NebulaGraph 等图数据库共同遵循的事实标准。(二) TuGraphTuGraph 由蚂蚁集团与清华大学联合研发, 提供高性能 OLTP / OLAP 双引擎、内置图算法库以及兼容 OpenCypher 的查询接口, 在国际图数据库基准测试中多次取得性能榜首, 是国产图数据库的代表性产品之一。其核心服务程序 lgraph_server 在单节点模式下通过 7070 端口对外提供REST API 与 Web 管理界面, 通过 7687 端口提供 Bolt 协议供 Neo4j 兼容客户端连接, 通过 9090 端口提供 RPC 服务与 Prometheus 监控接入。TuGraph 同时配套了离线导入工具 lgraph_import、Web 端可视化的 DB Browser 以及完整的 Cypher 增删改查与算法存储过程体系。(三) Cypher查询语言Cypher 是一种声明式图查询语言, 关键字不区分大小写, 以模式匹配为核心表达力。节点写作 (变量名: 标签 {属性}), 关系写作 -[变量名: 关系类型]-, 路径写作 (a)-[r]-(b)。查询的基本范式为 MATCH 加 RETURN, 类比关系数据库的 SELECT。完整的增删改查能力分别由 CREATE 创建顶点与关系、SET 更新属性、DELETE 与 REMOVE 删除元素、MATCH 加 WHERE 检索四类语句承担, 复杂查询则通过路径模式 (a)-[*..n]-(b)、WITH 中间结果传递、聚合函数 count / sum / avg 与排序限量 ORDER BY、LIMIT 组合实现。TuGraph 在标准 Cypher 之外, 额外提供algo.shortestPath、algo.pagerank、algo.jaccard 等存储过程, 通过 CALL 语句调用。(四)数据集准备本次作业使用 Elliptic Bitcoin Transactions 数据集, 该数据集由比特币交易历史脱敏抽样而成, 广泛用于区块链反洗钱与可疑交易识别研究。数据集由两个 CSV 文件构成。elliptic_txs_classes.csv 共 203,769 行 (不含表头), 两列, 第一列 txId 为交易编号 (整数), 第二列class 为类别标签, 取值为 1 (非法交易, 共 4,545 条)、2 (合法交易, 共 42,019 条) 或 unknown (未标注, 共 157,205 条)。elliptic_txs_edgelist.csv 共 234,355 行 (不含表头), 两列, 第一列 txId1 为引用方交易编号, 第二列 txId2 为被引用方交易编号。两个文件经图建模后, 共同构成一张203,769 顶点、234,355 边的稀疏有向图。二、启动TuGraph平台(一)运行环境本次作业在 Windows 10 家庭版 (Build 19045, 64 位) 上完成。宿主机预先安装 Docker Desktop 4.73.0 (WSL2 后端), 启动后左下角显示 Engine running。TuGraph 选用官方运行时镜像tugraph/tugraph-runtime-ubuntu18.04, 版本号 4.3.1。宿主机为 12 核 CPU、约 7.5 GiB 可用内存。Web 端使用 Microsoft Edge 浏览器访问。(二)启动步骤启动 TuGraph 共需四步, 全部命令在 PowerShell 中依次执行。第一步, 拉取 TuGraph 运行时镜像。docker pull tugraph/tugraph-runtime-ubuntu18.04:4.3.1第二步, 为数据库文件目录与日志目录分别创建 Docker 命名卷, 实现数据持久化, 避免容器删除导致数据丢失。docker volume create tugraph-datadocker volume create tugraph-log第三步, 以后台模式启动 TuGraph 服务容器, 同时将容器内的 7070 (HTTP / Web)、7687 (Bolt 协议)、9090 (RPC) 三个端口映射至宿主机。docker run -d --name tugraph ^-p 7070:7070 -p 7687:7687 -p 9090:9090 ^-v tugraph-data:/var/lib/lgraph/data ^-v tugraph-log:/var/log/lgraph_log ^--restart unless-stopped ^tugraph/tugraph-runtime-ubuntu18.04:4.3.1 ^lgraph_server -c /usr/local/etc/lgraph.json -d run其中 -d 表示后台运行容器; -p 参数完成端口映射; -v 参数挂载持久化数据卷; --restart unless-stopped 保证宿主机重启后容器自动恢复。末尾的 lgraph_server 命令以前台模式启动 TuGraph 服务进程。第四步, 打开浏览器, 在地址栏输入 http://localhost:7070, 进入 TuGraph DB Browser 登录界面。图 1 TuGraph DB Browser 登录界面(三)系统登录使用 TuGraph 默认账号登录, 用户名 admin, 密码 73TuGraph。首次登录时, 系统强制跳转至修改密码界面, 要求输入原密码并将其修改为长度不少于八位且与默认密码不同的新密码。完成修改后再次以新密码登录, 系统跳转至 Cypher 工作台 (Workbench/Cypher) 主界面, 左侧导航栏依次显示 查询、建模、导入、插件、帮助 五个功能模块, 右上角显示当前账号 admin 与默认子图default。至此, TuGraph 平台启动并登录成功。图 2 系统登录成功, 进入 Cypher 工作台主界面三、数据集图建模与数据导入(一)图建模设计依据数据集两个 CSV 文件的字段结构, 设计如下属性图模型。顶点标签 Transaction 表示一笔比特币交易, 主键为 txId, 数据类型 INT64; 附带 class 属性, 数据类型 STRING, 用于存储类别标签。边标签 Refers 表示一笔交易引用另一笔交易的关系, 起止顶点的标签约束均为 Transaction。该模型在 TuGraph 中表达为以下 JSON 格式的导入配置, 文件命名为 import.json, 与两个 CSV 文件置于同一目录下。{schema: [{ label: Transaction, type: VERTEX,primary: txId,properties: [{ name: txId, type: INT64 },{ name: class, type: STRING }]},{ label: Refers, type: EDGE,constraints: [ [Transaction, Transaction] ]}],files: [{ path: elliptic_txs_classes.csv, header: 1, format: CSV,label: Transaction, columns: [txId, class] },{ path: elliptic_txs_edgelist.csv, header: 1, format: CSV,label: Refers, SRC_ID: Transaction, DST_ID: Transaction,columns: [SRC_ID, DST_ID] }]}schema 块声明全部顶点标签与边标签及其属性结构, files 块描述每个 CSV 文件如何映射到对应的标签, 其中 header 字段为 1 表示首行是表头需要跳过, columns 字段以位置顺序声明列对应的属性名。对于边文件, SRC_ID 与 DST_ID 字段指定起止顶点所属的标签, 配合 columns 中的SRC_ID 与 DST_ID 占位符即可建立顶点之间的关联。图 3 TuGraph 建模界面, 左侧顶点标签 Transaction 已创建, 右侧为图谱可视化(二)数据导入步骤TuGraph 提供命令行工具 lgraph_import 用于离线批量导入数据。导入采用临时容器方式执行, 将本机存放 CSV 与 import.json 的目录映射进容器内的 /import, 同时挂载预先创建的持久化数据卷, 命令执行完毕后容器自动销毁, 数据保留在数据卷中供 TuGraph 服务容器使用。docker run --rm ^-v tugraph-data:/var/lib/lgraph/data ^-v D:\path\to\tugraph-deploy\import:/import ^tugraph/tugraph-runtime-ubuntu18.04:4.3.1 ^bash -c cd /import lgraph_import -c import.json ^-d /var/lib/lgraph/data --overwrite 1 --v3 1lgraph_import 读取 import.json 声明的 schema, 按顺序解析顶点 CSV 与边 CSV, 将顶点数据写入 LMDB 主键索引, 将边数据写入 RocksDB SST 文件。在本机环境下, 全量导入用时约 1.7 秒。导入完成后启动 TuGraph 服务容器, 浏览器登录 DB Browser, 在 Cypher 工作台中分别执行以下两条 Cypher 语句, 对顶点数与边数进行核对。MATCH (n:Transaction) RETURN count(n) AS num_vertices图 4 顶点数核对结果: Transaction 顶点共 203,769 个MATCH ()-[r:Refers]-() RETURN count(r) AS num_edges图 5 边数核对结果: Refers 边共 234,355 条进一步执行下列语句, 调用 TuGraph 内置过程 db.vertexLabels() 与 db.edgeLabels() 列出当前子图全部顶点与边标签, 用以核对 schema 是否按预期建立。CALL db.vertexLabels() YIELD label RETURN 顶点 AS type, labelUNION ALLCALL db.edgeLabels() YIELD label RETURN 边 AS type, label图 6 Schema 标签清单, 顶点标签 Transaction, 边标签 Refers上述四项核对结果均与数据集公开统计完全一致, 表明 Elliptic 数据集已成功导入 TuGraph 默认子图 default。四、Cypher查询示例Cypher 语言完整的增删改查范式由 CREATE 创建顶点与关系、SET 更新属性、DELETE 与REMOVE 删除元素、MATCH 加 WHERE 检索四类语句构成, 其中 MATCH 是最常用且应用最广的查询语句。本节针对已导入的 Elliptic 数据集, 自行设计基础查询与复杂查询各一例, 分别展示标签过滤与聚合统计的基础用法, 以及内置最短路径算法的高级用法。(一)基础查询:按交易类别分组统计业务问题: Elliptic 数据集中三种类别 (非法、合法、未标注) 的交易数量各有多少, 哪一类占比最高。MATCH (n:Transaction)RETURN n.class AS class, count(*) AS cntORDER BY cnt DESC语句要点: 该查询以 MATCH 子句匹配全部 Transaction 顶点, 通过 n.class 属性触发隐式分组(Cypher 中没有显式 GROUP BY, 由聚合函数 count(*) 触发隐式分组), 最后以 cnt 字段降序排列。图 7 基础查询执行结果结果分析: 执行结果共三行, 未标注 (unknown) 157,205 条占 77.15 %, 合法 (2) 42,019 条占20.62 %, 非法 (1) 4,545 条占 2.23 %。数据集存在显著的类别不平衡, 非法与合法的样本比例约为 1 比 9.2, 未标注样本占绝对多数。该现象反映出真实场景下带标签反洗钱样本极为稀缺, 也是Elliptic 数据集被反复引用为半监督学习基准的根本原因。(二)复杂查询:两交易顶点之间的最短引用路径业务问题: 给定 txId 3181 与 txId 288734134 两笔具体交易, 在 Refers 引用关系所构成的有向图上, 它们之间是否存在连通路径? 最短路径包含几跳? 路径上经过哪些中间顶点和边。MATCH (a:Transaction {txId: 3181}),(b:Transaction {txId: 288734134})CALL algo.shortestPath(a, b, {}) YIELD nodeCount, totalCost, pathRETURN nodeCount, totalCost, path语句要点: TuGraph 的最短路径算法以内置存储过程 algo.shortestPath 形式提供, 调用范式为先 MATCH 后 CALL。MATCH 子句先把两个端点绑定为 NODE 变量 a 与 b, 再以 CALL ... YIELD ... 形式调用过程, 接收 nodeCount (路径顶点数)、totalCost (路径累计代价, 无权图等价于跳数) 与 path (顶点与边交错的完整路径) 三项返回字段; 过程的第三个参数 {} 为空配置, 表示使用默认的双向广度优先搜索。该写法与 Neo4j 内联式的 MATCH p shortestPath((a)-[*]-(b)) 存在差异, 跨平台迁移时需要按 TuGraph 规范改写。图 8 最短路径查询执行结果结果分析: 查询返回 nodeCount 4, totalCost 3, 表明两个端点之间存在一条长度为 3 跳的最短引用路径, 路径上共经过 4 个顶点与 3 条边。path 字段以 V[内部顶点 ID] 与 E[内部边 ID] 交错形式给出完整路径序列, 顶点的业务可读 txId 主键可通过额外 MATCH 查询展开, 其中内部顶点ID 与导入顺序绑定, 同一份业务数据在不同次导入后会得到不同的 V[...] 序号, 而 txId 始终稳定。3 跳的路径长度与 Elliptic 数据集的稀疏图特征相吻合 (顶点数 203,769, 边数 234,355, 平均出度仅 1.15), 稀疏图中两端可达的顶点对之间, 路径长度普遍较短。
图数据库 TuGraph 基本操作 作业一
发布时间:2026/5/21 7:39:18
一、基础知识介绍(一)图数据库图数据库以顶点 (Vertex / Node)、边 (Edge / Relationship) 与属性 (Property) 三种元素表达事物及其关联关系。顶点对应实体, 边对应实体之间的关系, 属性以键值对形式附着在顶点或边上。相较关系数据库, 图数据库把 关系 提升为存储层的一等公民, 对多对多、深度关联的查询尤为高效。在工业界, 属性图模型 (Property Graph Model) 已成为 Neo4j、TuGraph、NebulaGraph 等图数据库共同遵循的事实标准。(二) TuGraphTuGraph 由蚂蚁集团与清华大学联合研发, 提供高性能 OLTP / OLAP 双引擎、内置图算法库以及兼容 OpenCypher 的查询接口, 在国际图数据库基准测试中多次取得性能榜首, 是国产图数据库的代表性产品之一。其核心服务程序 lgraph_server 在单节点模式下通过 7070 端口对外提供REST API 与 Web 管理界面, 通过 7687 端口提供 Bolt 协议供 Neo4j 兼容客户端连接, 通过 9090 端口提供 RPC 服务与 Prometheus 监控接入。TuGraph 同时配套了离线导入工具 lgraph_import、Web 端可视化的 DB Browser 以及完整的 Cypher 增删改查与算法存储过程体系。(三) Cypher查询语言Cypher 是一种声明式图查询语言, 关键字不区分大小写, 以模式匹配为核心表达力。节点写作 (变量名: 标签 {属性}), 关系写作 -[变量名: 关系类型]-, 路径写作 (a)-[r]-(b)。查询的基本范式为 MATCH 加 RETURN, 类比关系数据库的 SELECT。完整的增删改查能力分别由 CREATE 创建顶点与关系、SET 更新属性、DELETE 与 REMOVE 删除元素、MATCH 加 WHERE 检索四类语句承担, 复杂查询则通过路径模式 (a)-[*..n]-(b)、WITH 中间结果传递、聚合函数 count / sum / avg 与排序限量 ORDER BY、LIMIT 组合实现。TuGraph 在标准 Cypher 之外, 额外提供algo.shortestPath、algo.pagerank、algo.jaccard 等存储过程, 通过 CALL 语句调用。(四)数据集准备本次作业使用 Elliptic Bitcoin Transactions 数据集, 该数据集由比特币交易历史脱敏抽样而成, 广泛用于区块链反洗钱与可疑交易识别研究。数据集由两个 CSV 文件构成。elliptic_txs_classes.csv 共 203,769 行 (不含表头), 两列, 第一列 txId 为交易编号 (整数), 第二列class 为类别标签, 取值为 1 (非法交易, 共 4,545 条)、2 (合法交易, 共 42,019 条) 或 unknown (未标注, 共 157,205 条)。elliptic_txs_edgelist.csv 共 234,355 行 (不含表头), 两列, 第一列 txId1 为引用方交易编号, 第二列 txId2 为被引用方交易编号。两个文件经图建模后, 共同构成一张203,769 顶点、234,355 边的稀疏有向图。二、启动TuGraph平台(一)运行环境本次作业在 Windows 10 家庭版 (Build 19045, 64 位) 上完成。宿主机预先安装 Docker Desktop 4.73.0 (WSL2 后端), 启动后左下角显示 Engine running。TuGraph 选用官方运行时镜像tugraph/tugraph-runtime-ubuntu18.04, 版本号 4.3.1。宿主机为 12 核 CPU、约 7.5 GiB 可用内存。Web 端使用 Microsoft Edge 浏览器访问。(二)启动步骤启动 TuGraph 共需四步, 全部命令在 PowerShell 中依次执行。第一步, 拉取 TuGraph 运行时镜像。docker pull tugraph/tugraph-runtime-ubuntu18.04:4.3.1第二步, 为数据库文件目录与日志目录分别创建 Docker 命名卷, 实现数据持久化, 避免容器删除导致数据丢失。docker volume create tugraph-datadocker volume create tugraph-log第三步, 以后台模式启动 TuGraph 服务容器, 同时将容器内的 7070 (HTTP / Web)、7687 (Bolt 协议)、9090 (RPC) 三个端口映射至宿主机。docker run -d --name tugraph ^-p 7070:7070 -p 7687:7687 -p 9090:9090 ^-v tugraph-data:/var/lib/lgraph/data ^-v tugraph-log:/var/log/lgraph_log ^--restart unless-stopped ^tugraph/tugraph-runtime-ubuntu18.04:4.3.1 ^lgraph_server -c /usr/local/etc/lgraph.json -d run其中 -d 表示后台运行容器; -p 参数完成端口映射; -v 参数挂载持久化数据卷; --restart unless-stopped 保证宿主机重启后容器自动恢复。末尾的 lgraph_server 命令以前台模式启动 TuGraph 服务进程。第四步, 打开浏览器, 在地址栏输入 http://localhost:7070, 进入 TuGraph DB Browser 登录界面。图 1 TuGraph DB Browser 登录界面(三)系统登录使用 TuGraph 默认账号登录, 用户名 admin, 密码 73TuGraph。首次登录时, 系统强制跳转至修改密码界面, 要求输入原密码并将其修改为长度不少于八位且与默认密码不同的新密码。完成修改后再次以新密码登录, 系统跳转至 Cypher 工作台 (Workbench/Cypher) 主界面, 左侧导航栏依次显示 查询、建模、导入、插件、帮助 五个功能模块, 右上角显示当前账号 admin 与默认子图default。至此, TuGraph 平台启动并登录成功。图 2 系统登录成功, 进入 Cypher 工作台主界面三、数据集图建模与数据导入(一)图建模设计依据数据集两个 CSV 文件的字段结构, 设计如下属性图模型。顶点标签 Transaction 表示一笔比特币交易, 主键为 txId, 数据类型 INT64; 附带 class 属性, 数据类型 STRING, 用于存储类别标签。边标签 Refers 表示一笔交易引用另一笔交易的关系, 起止顶点的标签约束均为 Transaction。该模型在 TuGraph 中表达为以下 JSON 格式的导入配置, 文件命名为 import.json, 与两个 CSV 文件置于同一目录下。{schema: [{ label: Transaction, type: VERTEX,primary: txId,properties: [{ name: txId, type: INT64 },{ name: class, type: STRING }]},{ label: Refers, type: EDGE,constraints: [ [Transaction, Transaction] ]}],files: [{ path: elliptic_txs_classes.csv, header: 1, format: CSV,label: Transaction, columns: [txId, class] },{ path: elliptic_txs_edgelist.csv, header: 1, format: CSV,label: Refers, SRC_ID: Transaction, DST_ID: Transaction,columns: [SRC_ID, DST_ID] }]}schema 块声明全部顶点标签与边标签及其属性结构, files 块描述每个 CSV 文件如何映射到对应的标签, 其中 header 字段为 1 表示首行是表头需要跳过, columns 字段以位置顺序声明列对应的属性名。对于边文件, SRC_ID 与 DST_ID 字段指定起止顶点所属的标签, 配合 columns 中的SRC_ID 与 DST_ID 占位符即可建立顶点之间的关联。图 3 TuGraph 建模界面, 左侧顶点标签 Transaction 已创建, 右侧为图谱可视化(二)数据导入步骤TuGraph 提供命令行工具 lgraph_import 用于离线批量导入数据。导入采用临时容器方式执行, 将本机存放 CSV 与 import.json 的目录映射进容器内的 /import, 同时挂载预先创建的持久化数据卷, 命令执行完毕后容器自动销毁, 数据保留在数据卷中供 TuGraph 服务容器使用。docker run --rm ^-v tugraph-data:/var/lib/lgraph/data ^-v D:\path\to\tugraph-deploy\import:/import ^tugraph/tugraph-runtime-ubuntu18.04:4.3.1 ^bash -c cd /import lgraph_import -c import.json ^-d /var/lib/lgraph/data --overwrite 1 --v3 1lgraph_import 读取 import.json 声明的 schema, 按顺序解析顶点 CSV 与边 CSV, 将顶点数据写入 LMDB 主键索引, 将边数据写入 RocksDB SST 文件。在本机环境下, 全量导入用时约 1.7 秒。导入完成后启动 TuGraph 服务容器, 浏览器登录 DB Browser, 在 Cypher 工作台中分别执行以下两条 Cypher 语句, 对顶点数与边数进行核对。MATCH (n:Transaction) RETURN count(n) AS num_vertices图 4 顶点数核对结果: Transaction 顶点共 203,769 个MATCH ()-[r:Refers]-() RETURN count(r) AS num_edges图 5 边数核对结果: Refers 边共 234,355 条进一步执行下列语句, 调用 TuGraph 内置过程 db.vertexLabels() 与 db.edgeLabels() 列出当前子图全部顶点与边标签, 用以核对 schema 是否按预期建立。CALL db.vertexLabels() YIELD label RETURN 顶点 AS type, labelUNION ALLCALL db.edgeLabels() YIELD label RETURN 边 AS type, label图 6 Schema 标签清单, 顶点标签 Transaction, 边标签 Refers上述四项核对结果均与数据集公开统计完全一致, 表明 Elliptic 数据集已成功导入 TuGraph 默认子图 default。四、Cypher查询示例Cypher 语言完整的增删改查范式由 CREATE 创建顶点与关系、SET 更新属性、DELETE 与REMOVE 删除元素、MATCH 加 WHERE 检索四类语句构成, 其中 MATCH 是最常用且应用最广的查询语句。本节针对已导入的 Elliptic 数据集, 自行设计基础查询与复杂查询各一例, 分别展示标签过滤与聚合统计的基础用法, 以及内置最短路径算法的高级用法。(一)基础查询:按交易类别分组统计业务问题: Elliptic 数据集中三种类别 (非法、合法、未标注) 的交易数量各有多少, 哪一类占比最高。MATCH (n:Transaction)RETURN n.class AS class, count(*) AS cntORDER BY cnt DESC语句要点: 该查询以 MATCH 子句匹配全部 Transaction 顶点, 通过 n.class 属性触发隐式分组(Cypher 中没有显式 GROUP BY, 由聚合函数 count(*) 触发隐式分组), 最后以 cnt 字段降序排列。图 7 基础查询执行结果结果分析: 执行结果共三行, 未标注 (unknown) 157,205 条占 77.15 %, 合法 (2) 42,019 条占20.62 %, 非法 (1) 4,545 条占 2.23 %。数据集存在显著的类别不平衡, 非法与合法的样本比例约为 1 比 9.2, 未标注样本占绝对多数。该现象反映出真实场景下带标签反洗钱样本极为稀缺, 也是Elliptic 数据集被反复引用为半监督学习基准的根本原因。(二)复杂查询:两交易顶点之间的最短引用路径业务问题: 给定 txId 3181 与 txId 288734134 两笔具体交易, 在 Refers 引用关系所构成的有向图上, 它们之间是否存在连通路径? 最短路径包含几跳? 路径上经过哪些中间顶点和边。MATCH (a:Transaction {txId: 3181}),(b:Transaction {txId: 288734134})CALL algo.shortestPath(a, b, {}) YIELD nodeCount, totalCost, pathRETURN nodeCount, totalCost, path语句要点: TuGraph 的最短路径算法以内置存储过程 algo.shortestPath 形式提供, 调用范式为先 MATCH 后 CALL。MATCH 子句先把两个端点绑定为 NODE 变量 a 与 b, 再以 CALL ... YIELD ... 形式调用过程, 接收 nodeCount (路径顶点数)、totalCost (路径累计代价, 无权图等价于跳数) 与 path (顶点与边交错的完整路径) 三项返回字段; 过程的第三个参数 {} 为空配置, 表示使用默认的双向广度优先搜索。该写法与 Neo4j 内联式的 MATCH p shortestPath((a)-[*]-(b)) 存在差异, 跨平台迁移时需要按 TuGraph 规范改写。图 8 最短路径查询执行结果结果分析: 查询返回 nodeCount 4, totalCost 3, 表明两个端点之间存在一条长度为 3 跳的最短引用路径, 路径上共经过 4 个顶点与 3 条边。path 字段以 V[内部顶点 ID] 与 E[内部边 ID] 交错形式给出完整路径序列, 顶点的业务可读 txId 主键可通过额外 MATCH 查询展开, 其中内部顶点ID 与导入顺序绑定, 同一份业务数据在不同次导入后会得到不同的 V[...] 序号, 而 txId 始终稳定。3 跳的路径长度与 Elliptic 数据集的稀疏图特征相吻合 (顶点数 203,769, 边数 234,355, 平均出度仅 1.15), 稀疏图中两端可达的顶点对之间, 路径长度普遍较短。