知识库

理解数据库增长

确定图大小的最简单方法是通过文件系统并对名为 *store.db* 的文件大小进行求和。例如,在 Linux 实现中,可以运行

$ du -hc $NEO4J_HOME/data/databases/graph.db/*store.db*

这应该在停止的数据库或最近已进行检查点的数据库上运行(即备份后立即运行)

这将产生类似于以下内容的输出

5.5M    neostore.labelscanstore.db
8.0K    neostore.labeltokenstore.db
4.0K    neostore.labeltokenstore.db.id
8.0K    neostore.labeltokenstore.db.names
4.0K    neostore.labeltokenstore.db.names.id
72M     neostore.nodestore.db
4.0K    neostore.nodestore.db.id
8.0K    neostore.nodestore.db.labels
4.0K    neostore.nodestore.db.labels.id
196M    neostore.propertystore.db
8.0K    neostore.propertystore.db.arrays
4.0K    neostore.propertystore.db.arrays.id
4.0K    neostore.propertystore.db.id
8.0K    neostore.propertystore.db.index
4.0K    neostore.propertystore.db.index.id
8.0K    neostore.propertystore.db.index.keys
4.0K    neostore.propertystore.db.index.keys.id
8.0K    neostore.propertystore.db.strings
4.0K    neostore.propertystore.db.strings.id
8.0K    neostore.relationshipgroupstore.db
4.0K    neostore.relationshipgroupstore.db.id
0       neostore.relationshipstore.db
4.0K    neostore.relationshipstore.db.id
0       neostore.relationshiptypestore.db
4.0K    neostore.relationshiptypestore.db.id
8.0K    neostore.relationshiptypestore.db.names
4.0K    neostore.relationshiptypestore.db.names.id
8.0K    neostore.schemastore.db
4.0K    neostore.schemastore.db.id
273M    total

最后一行报告图的总大小为 273M。这并不包括 Neo4j 事务日志(neostore.transaction.*)的大小,因为这些文件的大小和保留时间是用户可配置的。

在上面的列表中,输出来自一个包含 500 万个节点的图,所有节点都具有标签 :Person,每个节点都有一个名为 id 的属性,该属性的值从 1 到 500 万。这些数据是通过运行等效于以下内容的内容准备的

USING PERIODIC COMMIT 50000
LOAD CSV WITH HEADERS FROM 'file:///person.csv' AS row
CREATE (:Person { id: row.id}  );

因此,您会看到文件 neostore.labelscanstore*、neostore.nodestore* 和 neostore.propertystore* 占用了比其默认空间更多的空间。由于图没有关系,因此名为 neostore.relationship* 的文件实际上是空的。

显而易见,随着添加数据,文件的大小会增加。但是,这有一个例外,这可能会解释为什么添加更多数据实际上会导致数据库大小减小。

在上面的文件列表中,以 .id 结尾的文件(例如 neostore.nodestore.db.id)用作可以重复使用的 ID 的回收站。由于图只是用 500 万个 :Person 节点填充,并且没有删除任何内容,因此 neostore.nodestore.db.id 是空的,节点记录在 neostore.nodestore.db 中。但是,如果我们要删除所有 500 万个节点,我们会发现 neostore.nodestore.db 的大小不会减小,但 neostore.nodestore.db.id 的大小会增加到 39M。结果,我们看到图的总大小至少增加了 39M。现在,如果我们要重新插入 500 万个节点,那么 neostore.nodestore.db.id 的大小会减小,因为在添加新节点时,我们首先检查是否可以重复使用以前使用的 ID,如果是,则将其从 neostore.nodestore.db.id 中删除。由于 neostore.nodestore.db.id 有 500 万个可重复使用的 ID,并且我们添加了 500 万个节点,因此该文件在完成时将几乎为空(即 4.0K)。通过添加这些节点,neostore.nodestore.db.id 的大小从 39M 减小到 4.0k,数据库的总大小也以相同的方式减小。请注意,在此过程中,neostore.nodestore.db 的大小没有改变。

总之,相对于这两个文件,体验如下(文件大小在 neo4j stop 后捕获):

  • 步骤 1:空图

    0       neostore.nodestore.db
    4.0K    neostore.nodestore.db.id
  • 步骤 2:添加 500 万个 :Person 节点

    72M     neostore.nodestore.db
    4.0K    neostore.nodestore.db.id
  • 步骤 3:删除 500 万个 :Person 节点(即 CALL apoc.periodic.commit("match (n:Person) with n limit {limit} delete n return count(*)",{limit:50000});) — 此后图现在为空

    72M     neostore.nodestore.db
    39M     neostore.nodestore.db.id
  • 步骤 4:重新添加 500 万个 :Person 节点

    72M     neostore.nodestore.db
    4.0K    neostore.nodestore.db.id

现在,如果您已经完成步骤 3 以上并且不打算添加更多节点,但希望缩小文件的大小,您可能需要考虑使用 copy-store.sh。此实用程序将读取脱机数据库并复制出数据,而不包括任何已写入但不再使用的数据或可重复使用 ID 列表的开销。

对图运行 copy-store.sh(如步骤 3 完成时存在的图)以准备一个新图后,由此产生的新创建的 graph.db 现在将这两个文件定义为

0       neostore.nodestore.db
4.0K    neostore.nodestore.db.id