Node.js 如何在负载(多个并发查询)下提高ArangoDB性能?

Node.js 如何在负载(多个并发查询)下提高ArangoDB性能?,node.js,concurrency,performance-testing,arangodb,arangojs,Node.js,Concurrency,Performance Testing,Arangodb,Arangojs,我们使用ArangoDB和PostgreSQL存储几乎相同的数据。PostgreSQL用于执行关系数据库可以很好执行的一般类型的查询。ArangoDB被选中来执行诸如图遍历、查找最短路径等查询 目前,我们有一个在PostgreSQL中包含160000条记录的表和一个在ArangoDB中包含相同数量文档的集合 我们正在开发的API将同时被多个用户使用,所以我想检查的第一点是ArangoDB和PostgreSQL在负载下的性能。我创建了一个简单的负载测试,作为一个工作负载,它使用ArangoDB和P

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

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

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

查询使用“按日期筛选”字段选择前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端排队。现在,如果我运行load并尝试使用ArangoDB Web界面执行一些查询,那么查询将在不可预测的时间内进行(取决于当前的用户数量),然后返回结果,并显示它已在大约4秒钟内执行,但这不是真的。对我来说,ArangoDB一次只能执行一个查询,而所有其他查询都在排队

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

更新:

我们使用Arangodb3.0,并将其作为Docker容器(来自官方图片)运行,内存为1.5GB

样本文件(我们有大约16000份):

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

我使用以下查询创建了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\u id
上使用skiplist似乎可以最好地提高性能,将性能降低到0.20秒,而索引的内存消耗约为18MB。服务器重新启动后,查询需要1.5秒,因为必须在第一次访问时加载集合,并且需要重建索引。然而,后续查询通常需要0.2秒

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


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

能否请您添加您的系统规格、您正在使用的ArangoDB版本以及可能的示例文档和实际查询?添加到上面的帖子中。使用
db.\u解释(您的查询)
您的查询是否使用索引?虽然您
限制
结果集,
排序
将导致必须检查所有项目,但仅限制返回的结果。根据结果大小,可用RAM的数量可能有点低。根据可用的CPU资源,更多的
服务器。线程
可能有助于提高速度。要更好地了解ArangoDB内部的情况,我们需要更多的信息。对于这些查询,db._explain()的输出将是一个良好的开端。我们需要找出使用了哪些指数,以及我们是否可以改善这种情况。最有可能的是,在
\u键
截止日期
上组合使用skiplist索引可以改善这种情况。我们应该了解,
限制
以何种方式掩盖了上述错误的副作用-如果必须手动进行排序,则必须提前处理大量文档。是的,我可以按照您在我的电脑上描述的几乎准确的速度复制。但是,请注意,在我询问负载下查询的速度时,您描述的是单个查询的性能。因此,如果我使用与您相同的样本数据,然后对这些数据运行负载测试,我可以在单个用户上获得正常性能,但是当用户数量增加时,响应时间也会增加。下面是它的样子(请注意,PostgreSql响应时间更快):
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