存储格式

Neo4j 的存储引擎支持多种描述数据如何写入磁盘的存储格式。block 格式由于其卓越的性能和可扩展性,是企业版(Enterprise Edition)推荐的存储格式。block 格式使用先进的数据结构和内联(inlining)技术来增强数据局部性,从而实现更好的资源利用率。

aligned 是社区版(Community Edition)的默认格式。

standardhigh_limit 格式在 Neo4j 5.23 版本中已被弃用。不建议在新数据库中使用这些格式。有关这些格式弃用及其最终移除时间表的更多信息,请参阅 格式弃用

有关 Neo4j 4.4 中存储格式的信息,请参阅 Neo4j Admin 和 Neo4j CLI → Neo4j Admin → 显示存储信息

可用的存储格式

以下是可用格式及其功能的概述:

Block

企业版+

  • 除非指定了 db.format,否则为默认格式。

  • 性能: 查询速度快;使用先进的数据结构和内联技术以实现更好的数据局部性。使用动态记录和树结构来高效处理“增长型”数据。

  • 内存效率: 优化了数据的并置(collocation),使得较少的读取操作即可获取更多相关数据;增强了资源利用率。Block 格式意味着执行查询时只需加载少量页面,即减少了页面错误和 I/O 开销。

  • 属性访问: 属性与节点和关系一起存储在块(block)中,大大减少了访问属性所需的指针追踪(pointer chasing)次数。

  • 实体限制: 能够在大规模图形上运行。支持撰写本文时最高的限制。详情请参阅 Block 格式实体限制
    支持任意长度的令牌名称(包括标签、属性键和关系类型名称),最高可达 GQL 标识符最大长度 16,383 个字符。

  • 面向未来: 设计上无需存储迁移即可进行扩展和改进。无需重写存储即可获得数据类型或性能增强等新功能。

  • 支持向其他存储格式的迁移路径: 虽然不推荐,但您可以将存储格式从 block 更改为 alignedhigh_limit。请注意 high_limit 已弃用。aligned 格式的限制低于 block,因此您的图数据必须在这些缩减的限制范围内。

Aligned
  • 社区版及 Neo4j 5.22 之前所有企业版新数据库的默认格式。

  • 性能: 性能优于 standard,但需要稍微多一点的磁盘空间。

  • 内存效率: 基于 standard,但提高了内存效率。

  • 属性访问: 在磁盘上以类似链表的数据结构存储图形数据。

  • 实体限制: 支持一定限制内的图。详情请参阅 Aligned 格式实体限制

  • 支持向其他存储格式的迁移路径: 您可以将存储格式从 aligned 更改为 blockhigh_limit。请注意 high_limit 格式已弃用,因此不建议迁移到该格式。

High_limit

企业版 5.23 版本弃用

  • 性能: 性能略低于 standard,且需要更多磁盘空间,但允许存储更多的节点和关系。

  • 内存效率: 基于 standard,但提高了内存效率。

  • 属性访问: 在磁盘上以类似链表的数据结构存储图形数据。

  • 实体限制: 在记录格式中,支持撰写本文时最高的限制。有关详细信息,请参阅 High_limit 格式实体限制

  • 有关弃用和最终移除的信息,请参阅 格式弃用

  • 支持向其他存储格式的迁移路径: 您只能迁移到 block 格式。

Standard

5.23 版本弃用

  • 性能: 基础、奠基性的格式。

  • 属性访问: 在磁盘上以类似链表的数据结构存储图形数据。

  • 实体限制: 支持一定限制内的图。详情请参阅 Standard 格式实体限制

  • 有关弃用和最终移除的信息,请参阅 格式弃用

  • 支持向其他存储格式的迁移路径: 您可以将存储格式从 standard 更改为 alignedblockhigh_limit。然而,不建议迁移到 high_limit 格式,因为它已被弃用。

格式弃用

standardhigh_limit 格式从 Neo4j 5.23 版本开始弃用。

block 格式比已弃用的格式提供更好的性能和可扩展性。这些弃用格式将在 v5 及 vNext 服务器整个生命周期内保留在产品中。包含这些格式的最后一个 Neo4j 版本将是 vNext.LTS,计划于 2026 年 11 月发布。Neo4j 的 LTS 版本在发布后提供 3 年支持。这意味着对 standardhigh_limit 格式的支持计划于 2029 年 11 月结束。

建议企业版用户尽早将所有数据库迁移至 block 格式,以确保最佳性能。有关详细信息,请参阅 更改现有数据库的存储格式

常见问题 (FAQ)
  1. 如何查看我的数据库格式?
    您可以使用 Cypher 命令 SHOW DATABASES YIELD name, store 获取数据库存储格式的信息。有关详细示例,请参阅 显示特定数据库的详细信息

  2. standardhigh_limit 格式的支持何时结束?
    包含这些格式的最后一个 Neo4j 版本将是计划于 2026 年 11 月发布的 LTS 版本,该版本将提供三年的支持,直至 2029 年 11 月。

  3. 如何更改数据库的存储格式?
    有关更改现有数据库存储格式的信息,请参阅 更改现有数据库的存储格式

  4. 我可以从哪些存储格式进行迁移,以及可以迁移到哪些格式?
    有关支持的迁移路径的信息,请参考 Neo4j Admin → 迁移数据库

如何设置数据库存储格式

您可以在创建新数据库时设置存储格式,也可以更改现有数据库的存储格式。

创建新数据库

只要未指定 db.format 设置,block 就是所有新创建数据库的默认格式。
如果您想更改它,可以在 neo4j.conf 文件中为 db.format 配置设置一个新值。
您也可以通过在创建数据库的命令中传递新格式作为参数来以特定存储格式创建数据库,例如 neo4j-admin database import fullneo4j-admin database copy 命令,或者在 Cypher 命令 CREATE DATABASE 中使用 storeFormat: 选项。

以下示例展示了如何以 block 存储格式创建新数据库。这同样适用于其他格式。

使用 neo4j-admin database import full 命令导入数据库时指定存储格式
bin/neo4j-admin database import full ... --format=block blockdb
使用 neo4j-admin database copy 命令复制数据库时指定存储格式
bin/neo4j-admin database copy --to-format="block" mydb blockdb
使用 CREATE DATABASE Cypher 语句创建新数据库时指定存储格式
CREATE DATABASE blockdb OPTIONS {storeFormat: 'block'}

更改现有数据库的存储格式

block 格式是企业版的默认格式,因为它具有卓越的性能和可扩展性。因此,建议将所有数据库迁移到 block 格式以确保最佳性能。
block 格式支持任意长度的令牌名称(包括节点标签、属性键和关系类型名称),最长可达 GQL 标识符最大长度 16,383 个字符。因此,从 aligned 迁移到 block 格式时,令牌名称必须遵守此长度限制。

standardhigh_limit 格式在 5.23 版本中被弃用,并将在未来版本中移除。有关更多信息,请参阅 格式弃用

请注意,更改存储格式会更改分配给节点和关系的内部 ID。这是因为 ID 代表了元素在存储文件中的物理位置。

更改存储格式是一个 I/O 密集型的离线操作,它会以新格式重写所有数据。因此,它要求:

  • 磁盘上有足够的空间存放数据库的旧副本和新副本。在迁移到 block 格式期间,数据库会进行内在的压缩。因此,迁移所需的磁盘空间大约与数据库的大小相同。您可以使用 数据库存储大小指标 来确定您的可用磁盘空间和潜在的可重用空间。

  • 图数据符合新格式的 实体限制

对于大型数据库,更改存储格式可能是一个耗时的操作,并且还需要重新填充任何索引。所需时间取决于数据库的大小、索引的数量、存储设备的速度以及可用内存量。例如,在最优条件下,100GB 的数据库可能需要 10 分钟,而在最坏情况下可能超过一个小时。因此,建议在备份上进行预演,以估计迁移所需的时间。

在单机服务器中

在单机服务器中更改现有数据库的存储格式需要数据库处于离线状态。以下步骤假设您想将名为 mydb 的数据库迁移到 block 格式,但同样的步骤也适用于其他格式。

  1. 使用 Cypher 命令 STOP DATABASE mydb 停止数据库。

  2. 使用以下任一选项更改已停止数据库的存储格式:

    • 使用 neo4j-admin database migrate 命令迁移现有数据库。

      您无需在运行 neo4j-admin database migrate 之前运行带有 --compact-node-store 选项的 neo4j-admin database copy。数据库在迁移过程中会自动进行压缩。

      例如:

      bin/neo4j-admin database migrate --to-format="block" mydb
    • 在使用 neo4j-admin database copy 命令创建现有数据库的副本时,将新的存储格式作为参数传递。您还可以设置 --copy-schema 选项以自动复制模式定义。例如:

      bin/neo4j-admin database copy --to-format="block" mydb blockdb --copy-schema
  3. 成功完成后,使用 Cypher 命令 START DATABASE mydb 启动数据库。索引会在数据库第一次启动时填充,如果存在属性唯一性约束,这可能需要一些时间。

在集群中

在集群中更改现有数据库的存储格式,要求您在一台服务器上恢复要迁移的数据库的备份,然后将该服务器用作其他集群成员的 指定种子节点(designated seeder),以便其他成员从中复制该数据库。

以下步骤假设您想将名为 mydb 的数据库迁移到 block 格式,但同样的步骤也适用于其他格式。该数据库托管在三台处于主模式(primary mode)的服务器上。

在一台服务器 server01 上:

  1. 在 Cypher Shell 中,使用 Cypher 命令 ALTER DATABASE databasename​ SET ACCESS READ ONLY 将要迁移的数据库设置为只读模式。例如:

    @system> ALTER DATABASE mydb SET ACCESS READ ONLY;
  2. 在您的命令行工具中,使用带有 --include-metadata=all 选项的 neo4j-admin database backup 命令备份该数据库,以包含与其相关的所有用户和角色。例如:

    bin/neo4j-admin database backup mydb --to-path=/path/to/your-backup-folder --include-metadata=all

    该命令会创建一个包含数据库及其关联元数据的备份归档。

  3. 在 Cypher Shell 中,删除该数据库及其所有相关的用户和角色:

    @system> DROP DATABASE mydb;
  4. 在命令行工具中,使用 neo4j-admin database restore 命令恢复您创建的备份:

    bin/neo4j-admin database restore --from-path=/path/to/your-backup-folder/mydb-2024-03-05T11-26-38.backup mydb
  5. 将恢复后的数据库迁移到 block 格式。

    您无需在运行 neo4j-admin database migrate 之前运行带有 --compact-node-store 选项的 neo4j-admin database copy。数据库在迁移过程中会自动进行压缩。

    bin/neo4j-admin database migrate --to-format="block" mydb
  6. 在 Cypher Shell 中,运行 SHOW SERVERS 查找 server01 的服务器 ID。交叉引用地址以找到服务器 ID。使用任何数据库进行连接。

    SHOW SERVERS YIELD serverId, name, address, state, health, hosting

在其中一台服务器上:

  1. 使用 system 数据库,并使用 server01 的服务器 ID 创建迁移后的数据库 mydbmydb 的拓扑结构存储在 system 数据库中,当您创建它时,它会根据默认拓扑进行分配(可以通过 CALL dbms.showTopologyGraphConfig 查看)。有关更多信息,请参阅 指定种子节点

    CREATE DATABASE mydb OPTIONS {existingData: 'use', existingDataSeedInstance: '<server01 id>'}
  2. 使用 Cypher 命令 SHOW DATABASE mydb 验证数据库是否已创建并可用。

  3. 成功完成后,恢复角色和权限。有关更多信息,请参阅 恢复用户和角色元数据

验证存储格式

您可以使用以下 Cypher 验证数据库的存储格式:

SHOW DATABASES YIELD name, store
结果
+----------------------------------+
| name      | store                |
+----------------------------------+
| "blockdb" | "block-block-1.1"    |
| "neo4j"   | "record-aligned-1.1" |
| "system"  | "record-aligned-1.1" |
+----------------------------------+

此外,您可以使用 neo4j-admin database info 命令获取有关数据库存储格式的详细信息。有关详细信息,请参阅 显示存储信息

存储格式和实体限制

下表显示了格式与 Neo4j 版本的兼容性以及不同存储格式的限制:

Block 格式

表 1. Block 格式与 Neo4j 版本兼容性
名称 存储格式版本 引入版本 GA 版本 默认版本

BLOCK_V1

block-block-1.1

5.14.0

5.16.0

5.22.0

表 2. Block 格式实体限制
名称 限制

节点

2^48 (281 474 976 710 656)

关系

(无定义的上限)

属性

(无定义的上限)

标签

2^31 (2 147 483 648)

关系类型

2^30 (1 073 741 824)

属性键

2^31 (2 147 483 648)

Aligned 格式

表 3. Aligned 格式与 Neo4j 版本兼容性
名称 存储格式版本 引入版本 默认版本 不支持的版本

ALIGNED_V5_0

record-aligned-1.1

5.0.0

CE, EE < Neo4j 5.22

ALIGNED_V4_3

AF4.3.0

4.3.0

5.0.0

ALIGNED_V4_1

AF4.1.a

4.1.0

5.0.0

表 4. Aligned 格式实体限制
名称 限制

属性键

2^24 (16 777 216)

节点

2^35 (34 359 738 368)

关系

2^35 (34 359 738 368)

属性

2^36 (68 719 476 736)

标签

2^31 (2 147 483 648)

关系类型

2^16 (65 536)

关系组

2^35 (34 359 738 368)

Standard 格式

有关弃用和最终移除的信息,请参阅 格式弃用

表 5. Standard 格式与 Neo4j 版本兼容性
名称 存储格式版本 引入版本 不支持的版本

STANDARD_V5_0

record-standard-1.1

5.0.0

STANDARD_V4_3

SF4.3.0

4.3.0

5.0.0

STANDARD_V4_0

SF4.0.0

4.0.0

5.0.0

STANDARD_V3_4

v0.A.9

3.4.0

5.0.0

表 6. Standard 格式实体限制
名称 限制

属性键

2^24 (16 777 216)

节点

2^35 (34 359 738 368)

关系

2^35 (34 359 738 368)

属性

2^36 (68 719 476 736)

标签

2^31 (2 147 483 648)

关系类型

2^16 (65 536)

关系组

2^35 (34 359 738 368)

High_limit 格式

有关弃用和最终移除的信息,请参阅 格式弃用

表 7. High_limit 格式与 Neo4j 版本兼容性
名称 存储格式版本 引入版本 不支持的版本

HIGH_LIMIT_V5_0

record-high_limit-1.1

5.0.0

HIGH_LIMIT_V4_3_0

HL4.3.0

4.3.0

5.0.0

HIGH_LIMIT_V4_0_0

HL4.0.0

4.0.0

5.0.0

HIGH_LIMIT_V3_4_0

vE.H.4

3.4.0

5.0.0

HIGH_LIMIT_V3_2_0

vE.H.3

3.2.0

5.0.0

HIGH_LIMIT_V3_1_0

vE.H.2

3.1.0

5.0.0

HIGH_LIMIT_V3_0_6

vE.H.0b

3.0.6

5.0.0

HIGH_LIMIT_V3_0_0

vE.H.0

3.0.0

5.0.0

表 8. High_limit 格式实体限制
名称 限制

属性键

2^24 (16 777 216)

节点

2^50 (1 千万亿)

关系

2^50 (1 千万亿)

属性

2^50 (1 千万亿)

标签

2^31 (2 147 483 648)

关系类型

2^24 (16 777 216)

关系组

2^50 (1 千万亿)

存储的数据元素

Neo4j 图数据模型由节点、关系、属性及其数据组成。每个元素存储以下数据:

  • 节点:唯一 ID、标签集合(节点可以有多个标签或没有标签)、属性集合、关系集合(节点可以有多个关系或没有关系)。

  • 关系:唯一 ID、类型、源节点、目标节点、属性集合。

  • 属性:键值对。

所有图数据文件都存储在 $NEO4J_HOME/data/databases/databasename 下。

Block 格式存储文件

block 格式中,所有图元素都存储在一组以 block. 为前缀的存储文件中。以下是三种最重要的存储类型、相关文件、包含的数据、每条记录的大小及其用途的概述:

Small store

block.x1.db

主要的存储文件,用于保存节点和关系的初始数据。在许多数据集中,大多数节点都适合此存储。创建节点时,会在此文件中创建一个 128 字节的静态块,位于 偏移量 = 128 字节 * 节点ID 处。它由两个 64 字节的记录组成:节点数据记录存储标签和节点属性,关系数据记录存储与该节点连接的关系和关系数据。编码尝试将尽可能多的数据放入此块中,通常最多 10 个标签、6-7 个属性和最多 5 个关系。能够容纳的数据量在很大程度上取决于数据的类型和大小。如果您有更多的标签,但没有属性或属性很小,则可以容纳更多的标签,反之亦然。关系也是如此。如果关系属性较少,则可以容纳更多关系,反之亦然。请记住,如果没有数据存在,该块仍占用 128 字节。只要节点存在,此块就会持续存在。

Dynamic stores

当与节点或关系连接的数据超过 Small store 的容量时,会使用动态存储。存在以下动态存储文件:

block.node.xd.db

此文件存储节点的动态记录。当节点的标签或属性数据超过 block.x1.db 存储中记录的 64 字节容量时,会在此文件中分配一条记录。动态记录的大小定义为 大小 = X * 128,其中 X 的选择足以容纳所有标签和属性,最大总大小为 8192 字节。block.x1.db 中的记录存储对此动态记录的引用。随着节点数据的添加或删除,此记录会调整为新大小,在此过程中可能会重新定位。此记录通常可以包含数百个标签或属性。

block.relationship.xd.db

与节点动态存储类似,当关系数据超过 block.x1.db 存储中记录的 64 字节容量,或者节点至少有一个密集(dense)关系时,会在此文件中分配一条记录。该记录的大小也会调整为关系数据的总大小,最大大小为 2047 字节。block.x1.db 中的记录存储对此动态记录的引用。此记录通常可以包含数百个关系。

block.big_values.db

所有总 大小 < ~31 字节 的属性都会与 Small 或 Dynamic store 中的节点和关系数据进行内联。
编码后超过 31 字节的属性(通常是较长的字符串或数组)存储在此文件中,并用引用代替该值。这些记录的大小会根据属性值的编码大小进行调整,其中 大小 = X * 64 字节,最大记录大小为 8192 字节。如果属性的编码大小超过最大记录大小,数据将被拆分为多个记录,并作为链表链接在一起。有关详细信息,请参阅 Block 格式中大属性值的空间重用

Dense stores

当与节点和关系连接的数据超过 Small 和 Dynamic store 的容量时,数据存储在 Dense store 文件中。它基于一种多根代际 B+ 树结构,允许高效地存储和检索大量数据,其中每个节点都有一个单独的根。存在以下 Dense store 文件:

block.relationship.dense.db

关系 Dense store 为具有大量关系的节点保存关系。当节点的关系数据超过动态关系记录的最大大小时,溢出的关系会移动到此存储中。它利用树结构,按关系类型和方向为任何给定的节点进行排序。一个节点的部分关系可以位于 block.x1.dbblock.relationship.xd.db 存储中,而其他关系位于 Dense store 中。同一类型的所有关系将始终位于同一个存储中。对于任何给定的节点,可以放置在 Dense store 中的关系数量没有上限。

block.huge.db

Huge store 保存极其大量的标签或属性数据。当节点或关系包含无法容纳在任何其他存储中的更多标签或属性数据时,它会进入 Huge store。这种情况通常发生在包含数千个属性的实体中。