【问题标题】:Neo4j database size growsNeo4j 数据库大小增长
【发布时间】:2016-06-11 07:23:49
【问题描述】:

我正在使用 neo4j 3.0.1 社区,我有几 GB 的数据。这些数据很快就会过时(比如每天 2.3 次),我必须先创建新数据,然后删除旧数据(因此在任何时候都有一些数据可用)。

问题在于 neo4j 不会重用已删除节点/关系中的空间。 我使用 MATCH (n) WHERE 条件 DETEACH DELETE n

我可以看到节点正在被删除(它们的数量是恒定的 ~30M),但大小正在增长(在 12 次更新后,大小几乎正好是应有大小的 12 倍)。

我找到了以前的帖子 Neo4J database size / shrinking 关于store-utils,但我想找到更好的解决方案。

我还发现了旧问题(来自版本 1.x)neostore.* file size after deleting millions node,但至少在我的情况下,它根本不像答案那样工作。

有一些建议可以删除所有数据库文件并创建一个新文件,但这需要停止服务,这是不应该发生的。

我还发现了一些信息,为了重用空间,您需要先重新启动 DB,也尝试过,但没有成功。

有没有办法从已删除的节点/关系中有效地释放/重用空间?也许我错过了一些配置,或者它仅在企业版中可用?

编辑:

最后我有一些时间进行测试,我运行了几次刷新数据的场景,也重新启动了几次服务器。在 windows 10 环境下的 neo4j 3.0.0 上进行了测试。结果是(尚未允许嵌入图像):

neo4j storage sizes

每一列表示存储大小以供进一步更新,蓝线表示neo4j服务器重启,最后一列(用棕色线分隔)代表运行store-utils后的大小。

如前所述,大小增长得相当快,并且根据文档,重新启动没有帮助。只有 store-utils 有帮助(他们清理除了 neostore.nodestore.db 之外的文件),但将 store-utils 集成到生产解决方案将是一个困难且混乱的解决方案。

谁能给我一个提示,为什么存储空间会增长?

【问题讨论】:

    标签: neo4j graph-databases


    【解决方案1】:

    您可以在创建新数据后重新启动服务器,因此下次创建数据时,它将重新使用您上次释放的块,这只会留下 2 倍的容量(如果您必须先保留数据在删除之前)。

    您第一次仍然应该使用 store-utils 来压缩您的商店。

    【讨论】:

    • 我刚刚这样做了,但空间没有被重复使用。不确定这是否会有所不同,但我在 docker 容器中运行 neo4j 并且我正在重新启动整个容器(所以我猜 neo4j 不会很好地停止)。我也很肯定,当我在没有 docker 的情况下测试 neo4j 时,它也没有重用空间。我正在使用“neo4j 控制台”命令启动 neo4j,并通过停止进程来停止它。
    【解决方案2】:

    从 Neo4j 3.0.4 开始,企业版支持重用节点 ID 和关系 ID,而无需重新启动实例。这适用于单实例和 HA 部署。

    要启用该功能,您需要在neo4j.conf 中设置以下内容:

     dbms.ids.reuse.types.override=NODE,RELATIONSHIP
    

    【讨论】:

    【解决方案3】:

    经过大量测试后,我终于找到了问题的主要根源——事实证明,我在 neo4j 服务器上进行了硬关机,他无法处理,结果他在删除节点/关系和重用它们之后的空间方面遇到了困难。

    让我们从头开始。 我在docker下使用neo4j(使用docker compose)。 我的场景非常简单,每隔几个小时我就会开始一个进程,在该进程中添加几 GB 的节点,完成后我会从前一个进程中删除节点(非常简短)。有时我必须更新 neo4j 插件或做一些需要我重新启动服务器的工作,这就是问题开始的地方。我正在使用 docker-compose 重新启动它,它从不等待 neo4j 优雅地退出(默认情况下,当我知道问题时,我现在必须对其进行自定义),而是立即杀死他。在 debug.log 中没有停止服务器的痕迹。 Neo4j 不处理它,结果他做了很奇怪的事情。当我启动服务器时,他回滚 nodeId 计数器、relationshipId 计数器和其他,并且在节点/关系之后不释放空间,但至少他从不回滚节点和关系本身。当然,我的删除操作已在事务中成功提交,所以这不是恢复未提交更改的情况。几次重新启动和导入后,我的数据库大小乘以导入次数。节点计数器也被严重夸大了。

    我意识到杀死 neo4j 主要是我的错,但我认为这种行为仍然不理想。

    还有另一个相关的问题。我进行了几乎 24 小时的测试,没有重新启动,在此期间我重复了我的场景超过 20 次。我对每次导入的增长时间感到非常惊讶(跳过不断增长的数据库大小问题)

    进口天然橡胶。 |创建节点时间 |删除节点时间

    1 | 20 分钟 | 0 分钟(尚无可删除的内容)

    2 | 20 分钟 | 8 分钟

    3 | 20 分钟 | 12 分钟

    ...

    ~20 | 20 分钟 |超过 80 分钟

    如您所见,节点/关系很可能不会立即删除(也许它们实际上在停止/启动期间被删除)并且我的删除脚本必须做很多额外的工作。

    这是我的删除代码:

    String REMOVE_OLD_REVISION_NODES_QUERY =
        "MATCH (node) " +
                    "WHERE node.revision <> {" + REVISION_PARAM + "} " +
                    "WITH node LIMIT 100000 " +
                    "DETACH DELETE node " +
                    "RETURN count(node) as count";
    LOG.info("Removing nodes with revision different than: {}", revision);
    long count;
    do {
        count = (long) graphDb.execute(REMOVE_OLD_REVISION_NODES_QUERY, ImmutableMap.of(REVISION_PARAM, revision)).columnAs("count").next();
    } while (count > 0);
    

    当我重新启动 docker 映像时,我可能能够解决杀死 neo4j 的问题(添加一些脚本以确保 neo4j 能够正常停止),但不确定是否有办法处理不断增长的大小和删除时间(除非我在每次更新后重新启动 neo4j)。

    我正在描述这个问题,所以也许有一天它会帮助某人,或者帮助 neo4j 团队改进他们的产品,因为它是我曾经使用过的最令人愉快的数据库,尽管我必须处理这些问题。

    【讨论】:

      猜你喜欢
      • 2022-10-19
      • 1970-01-01
      • 2014-05-12
      • 2017-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多