【问题标题】:How to improve ArangoDB performance under the load (multiple concurrent queries)?如何提高负载下的 ArangoDB 性能(多个并发查询)?
【发布时间】:2016-08-04 11:53:19
【问题描述】:

我们使用 ArangoDB 和 PostgreSQL 来存储几乎相同的数据。 PostgreSQL 用于执行关系数据库可以很好地执行的一般类型的查询。选择 ArangoDB 来执行图形遍历、查找最短路径等查询。

目前我们在 PostgreSQL 中有一个包含 160000 条记录的表,在 ArangoDB 中有一个包含相同数量文档的集合。

我们正在开发的 API 将被多个用户同时使用,所以我想检查的第一点是 ArangoDB 和 PostgreSQL 在负载下的表现。我创建了一个简单的负载测试,它作为工作负载使用过滤器对 ArangoDB 和 PostgreSQL 执行简单的选择查询。

查询使用按日期字段过滤的前 N ​​个记录/文档。

当我运行负载测试时,对 PostgreSQL 的所有查询都在 0.5 秒内执行,我将用户数量从 10 增加到 100,并且完全不影响执行时间。

当您从单个用户开始时,对 ArangoDB 的相同查询大约需要 2 秒,然后响应时间与并发用户数量成正比增长。对于 30 个并发用户,所有查询都会在等待 60 秒的回复后超时。

我尝试调试 arangojs 连接器,发现:

var maxTasks = typeof agent.maxSockets === 'number' ? agent.maxSockets * 2 : Infinity;

还有这个:

Connection.agentDefaults = {
  maxSockets: 3,
  keepAlive: true,
  keepAliveMsecs: 1000
};

这意味着默认的 arangojs 行为是同时向 ArangoDB 发送不超过 6 个并发查询,这导致所有其余查询在 Node.js 端排队。我试图增加数量,但没有帮助,现在看起来所有查询都在 ArandoDB 端排队。现在,如果我运行负载并尝试使用 ArangoDB Web 界面执行一些查询,则查询将等待不可预测的时间(取决于目前的用户数量),然后返回结果并告诉我它已被执行在大约 4 秒内,这是不正确的。对我来说,看起来 ArangoDB 一次只能执行一个查询,而所有其他查询都在排队......

我错过了什么吗?是否有任何设置可以调整 ArangoDB 并提高其在负载下的性能?

更新:

我们使用 ArangoDB 3.0 并将其作为具有 1.5 GB RAM 的 Docker 容器(来自官方图像)运行。

示例文档(我们有大约 16 000 个):

{
  "type": "start",
  "from_date": "2016-07-28T10:22:16.000Z",
  "to_date": "9999-06-19T18:40:00.000Z",
  "comment": null,
  "id": "13_start",
  "version_id": 1
}

AQL 查询:

FOR result IN @@collection 
   FILTER (result.version_id == 1) 
   FILTER (result.to_date > '2016-08-02T15:57:45.278Z') 
     SORT result._key 
     LIMIT 100 
     RETURN result

【问题讨论】:

  • 能否请您添加您的系统规格、您正在使用的 ArangoDB 版本以及示例文档和实际查询?
  • 添加到上面的帖子中。
  • 使用db._explain(yourQuery) 您的查询是否使用索引?虽然你LIMIT 结果集,SORT 将导致所有项目都必须被检查,只有返回的结果是有限的。根据结果​​大小可用 RAM 的数量可能有点少。根据可用的 CPU 资源,更多 server.threads 可能有助于提高速度。
  • 为了更好地了解 ArangoDB 内部发生的事情,我们需要更多信息。这些查询的 db._explain() 输出将是一个好的开始。我们需要找出,使用了哪些指标,以及我们是否可以改善这种情况。 _keyto_date 上的组合跳过列表索引很可能可以改善这种情况。我们应该了解,LIMIT 以何种方式掩盖了上述错误的副作用 - 如果必须手动进行排序,则必须提前处理大量文档。

标签: node.js concurrency performance-testing arangodb arangojs


【解决方案1】:

我使用以下查询创建了 160k 示例文档:

LET v = [1,1,1,1,1,2,2,2,3,3,4]
LET d = DATE_NOW()

FOR i IN 1..160000
INSERT {
  "type": "start",
  "from_date": DATE_SUBTRACT(d, RAND()*4000, "days"),
  "to_date": DATE_ADD(d, RAND()*4000+100, "days"),
  "comment": null,
  "id": CONCAT(i, "_start"),
  "version_id": v[RAND()*LENGTH(v)]
} INTO @@collection
RETURN NEW

同步到磁盘时,数据文件大约为 30MB。日志文件为 32MB。

如果在该数据集上运行查询,则报告的平均执行时间为 0.35 秒

我尝试了不同的索引,并且仅在 version_id 上的跳过列表似乎可以最大程度地提高性能,以大约 18MB 的索引内存为代价将其降低到 0.20 秒。在服务器重新启动后,查询需要 1.5 秒,因为必须在首次访问时加载集合并且需要重建索引。然而,后续查询始终需要 0.2 秒。

我使用了 ArangoDB 3.0.devel,它的性能应该与稳定的 3.0.x 版本大致相同。根据 Web 界面运行查询几次后,DBMS 使用的 RAM 约为 440MB。

如果您一直看到查询时间 >1.0 秒,则说明有问题。如果集合被自动卸载(可能是由于 RAM 不足引起),您能否在查询之间进行检查?如果是这样,请检查是什么占用了您的内存(如果它甚至是 ArangoDB),并确保您尝试使用更多 RAM 以查看它是否会影响查询时间。其他资源是否会限制性能,例如大容量存储或 CPU?

【讨论】:

  • 是的,我几乎可以重现您在我的电脑上描述的速度。但是,请注意,当我询问负载下的查询速度时,您描述的是单个查询的性能。因此,如果我使用与您相同的示例数据,然后对这些数据运行负载测试,我会在单个用户的情况下获得正常的性能,但是当用户数量增加时,响应时间也会增加。这是它的样子(注意 PostgreSql 响应时间更快):cloud.mail.ru/public/3yyY/joAXFwxVD
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-03
  • 1970-01-01
  • 1970-01-01
  • 2014-07-17
  • 1970-01-01
相关资源
最近更新 更多