大量插入杀死 arangod(好吧,几乎)
Massive inserts kill arangod (well, almost)
我想知道有没有人遇到过这种情况:
当通过 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
(其中 users 包含 500000 个条目),会发生以下情况
- canSee 变得完全锁定(也不再读取)
- 内存消耗增加
- arangosh 或网络控制台变得无响应
- 失败 [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'
最佳
以上查询将在单个事务中将 5M 文档插入 ArangoDB。这将需要一段时间才能完成,并且当事务仍在进行时,它将在内存中保存大量(可能需要的)回滚数据。
此外,上面的查询将首先建立所有要插入内存的文档,一旦完成,将开始插入它们。构建所有文档也会消耗大量内存。执行此查询时,您会看到内存使用量稳步增加,直到某个时候磁盘写入将在实际插入开始时启动。
至少有两种改进方法:
将查询拆分为多个较小的事务可能会有所帮助。这样每个事务就不会像原始事务那么大,并且在进行时不会阻塞那么多系统资源。
对于上面的查询,技术上没有必要先建立所有文档插入内存,然后才将它们全部插入。相反,从 users
读取的文档可以在到达时插入到 canSee
中。这不会加快查询速度,但会显着降低在查询执行期间对与上述一样大的结果集的内存消耗。它还将导致写入立即开始,从而更早地开始预写日志收集。并非所有查询都符合此优化条件,但有些(包括上述)符合条件。我今天研究了一种机制,可以检测符合条件的查询并以这种方式执行它们。该更改已于今天推送到 devel 分支,并将在 ArangoDB 2.5 中可用。
我想知道有没有人遇到过这种情况:
当通过 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
(其中 users 包含 500000 个条目),会发生以下情况
- canSee 变得完全锁定(也不再读取)
- 内存消耗增加
- arangosh 或网络控制台变得无响应
- 失败 [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'
最佳
以上查询将在单个事务中将 5M 文档插入 ArangoDB。这将需要一段时间才能完成,并且当事务仍在进行时,它将在内存中保存大量(可能需要的)回滚数据。
此外,上面的查询将首先建立所有要插入内存的文档,一旦完成,将开始插入它们。构建所有文档也会消耗大量内存。执行此查询时,您会看到内存使用量稳步增加,直到某个时候磁盘写入将在实际插入开始时启动。
至少有两种改进方法:
将查询拆分为多个较小的事务可能会有所帮助。这样每个事务就不会像原始事务那么大,并且在进行时不会阻塞那么多系统资源。
对于上面的查询,技术上没有必要先建立所有文档插入内存,然后才将它们全部插入。相反,从
users
读取的文档可以在到达时插入到canSee
中。这不会加快查询速度,但会显着降低在查询执行期间对与上述一样大的结果集的内存消耗。它还将导致写入立即开始,从而更早地开始预写日志收集。并非所有查询都符合此优化条件,但有些(包括上述)符合条件。我今天研究了一种机制,可以检测符合条件的查询并以这种方式执行它们。该更改已于今天推送到 devel 分支,并将在 ArangoDB 2.5 中可用。