大量插入杀死 arangod(好吧,几乎)

Wir*_*tsi 2 arangodb

我想知道有人遇到过这个:

通过 AQL 插入文档时,我可以轻松杀死我的 arango 服务器。例如

FOR i IN 1 .. 10
  FOR u IN users
    INSERT {
        _from: u._id,
        _to: CONCAT("posts/",CEIL(RAND()*2000)),
        displayDate: CEIL(RAND()*100000000)
    } INTO canSee
Run Code Online (Sandbox Code Playgroud)

(其中用户包含 500000 个条目),会发生以下情况

  • canSee 变得完全锁定(也不再读取)
  • 内存消耗上升
  • arangosh 或 Web 控制台变得无响应
  • 失败 [ArangoError 2001: 无法连接]
  • 服务器仍在运行,访问集合会超时
  • 大约需要 5-10 分钟,直到服务器恢复,我才能再次访问该集合
  • 访问任何其他集合工作正常

好吧,我正在创建很多条目,并且 AQL 可能会以批量执行的方式实现。通过 db.save 方法进行写入时,它可以工作,但速度要慢得多。

另外我怀疑这可能与预写缓存填满有关。

但是,有什么办法可以解决这个问题吗?将大量条目写入数据库不一定会杀死它。

日志说

DEBUG [./lib/GeneralServer/GeneralServerDispatcher.h:411] shutdownHandler called, but no handler is known for task

DEBUG [arangod/VocBase/datafile.cpp:949] created datafile '/usr/local/var/lib/arangodb/journals/logfile-6623368699310.db' of size 33554432 and page-size 4096

DEBUG [arangod/Wal/CollectorThread.cpp:1305] closing full journal '/usr/local/var/lib/arangodb/databases/database-120933/collection-4262707447412/journal-6558669721243.db'
Run Code Online (Sandbox Code Playgroud)

最好的

stj*_*stj 5

上述查询将在单个事务中向 ArangoDB 插入 5M 文档。这将需要一段时间才能完成,并且当事务仍在进行中时,它将在内存中保存大量(可能需要的)回滚数据。

此外,上面的查询将首先建立所有要插入内存的文档,一旦完成,将开始插入它们。构建所有文档也会消耗大量内存。执行此查询时,您将看到内存使用量稳步增加,直到某个时候磁盘写入将在实际插入开始时开始。

至少有两种方法可以改善这一点:

  • 将查询拆分为多个较小的事务可能会有所帮助。每个事务都不会像原始事务那么大,并且在进行时不会阻塞那么多系统资源。

  • 对于上面的查询,从技术上讲,没有必要先建立所有要插入内存的文档,然后才将它们全部插入。相反,读取的文档users可以在canSee到达时插入。这不会加快查询速度,但它会显着降低查询执行期间的内存消耗,用于与上述一样大的结果集。它还将导致立即开始写入,从而更早开始预写日志收集。并非所有查询都有资格进行此优化,但有些(包括上述)是。我今天研究了一种机制,可以检测符合条件的查询并以这种方式执行它们。该更改已于今天推送到 devel 分支,并将在 ArangoDB 2.5 中提供。

  • 我也经常有这样的疑问。在我的大多数情况下,我不需要事务安全性,但希望在一个 AQL 语句中向前推进。(典型情况是例如将事物预先计算到易变集合中时)。有没有办法在“无事务模式”中制定 AQL 语句? (2认同)