确保我们的数据库查询很快
#database #index #mongodb

作为Woovi量表,我们有越来越多的电荷和交易。费用代表付款请求,交易代表我们的商家银行帐户中的移动。我们的MongoDB数据库中的这两个集合非常大,而且仍然非常快。

确保我们不会推出引起COLLSCAN的新代码(阅读整个表),我们始终需要确保我们的查询使用适当的索引。

了解mongodb解释输出

我们首先需要了解MongoDB如何计划其查询。
为此,我们将使用命令db.collection.explain(),您可以在MongoDB docs

中阅读有关它的更多信息。

它可以有5种不同的操作:

  • COLLSCAN用于收集扫描
  • IXSCAN用于扫描索引键
  • FETCH用于检索文档
  • GROUP用于分组文档
  • SHARD_MERGE合并碎片结果
  • SHARDING_FILTER用于从碎片中过滤孤儿文档

COLLSCAN是最糟糕的情况,因为它需要扫描整个系列以查找一个项目,也就是o(n),对于像我们这样的大型收藏很慢。
IXSCAN是最好的操作,因为它在最坏的情况下使用索引平衡的b-tree(log(log(n))
FETCH是在他们需要检索更多文档的时候,用于分页
SHARD_MERGE是您有共享数据库的时候,需要合并一些碎片的结果
SHARDING_FILTER是您需要在碎片中过滤数据的时候。

自动化IXSCAN索引测试

我们在测试中使用内存中的mongoDB来确保我们的代码在数据库中执行正确的查询和聚合。这避免了嘲笑数据库时发生的许多假阳性和假否定。

当我们使用真实的mongoDB时,我们可以在执行查找或汇总时调用.explain()方法,而mongodb将返回查询计划者,显示数据库将如何执行查询的获胜计划。

检查我们查询是否使用索引的测试,在mongodb中称为IXSCAN,非常简单:

const getStageFromExplanation = (explanation: MongoExplanation) =>
  explanation.queryPlanner.winningPlan.inputStage.stage;

it('should test the ixscan from myquery', async () => {
  // force model index creation 
  await Model.syncIndexes();

  // create your test query
  const modelCursor = Model.find({
    name: 'Edu',
    age: '18',
  });

  // ask to explain
  modelCursor.explain();

  // wait for explanation
  const modelExplained = await modelCursor;

  //check if the query explanation uses index - IXSCAN
expect(getStageFromExplanation(modelExplained)).toEqual('IXSCAN');
});

我们执行查找,要求使用.explain方法进行解释,然后在查询计划者的获胜计划中检查IXSCAN。

总结

随着扩展的规模,您的数据库变得越来越重要,因此您无法将新代码推向使用CollScan或进行缓慢查询的生产。
在Woovi,我们对此性能检查进行自动化,以确保在将新代码推向生产之前使用适当的索引。
我们还在分期和生产环境中使用Kibana和Elastic APM监测性能回归。

参考


woi
Woovi是一家创业公司,使购物者能够按照自己的意愿付款。为了实现这一目标,Woovi为商人提供即时付款解决方案接受订单。

如果您想与我们合作,我们是hiring


Shiro hatoriUnsplash上的照片