在 Hapi 框架中遇到的 Mongoose 查询性能问题详解
在使用 Hapi 框架和 Mongoose 进行开发时,我们可能会遇到一些性能问题,尤其是在进行复杂查询时。这篇文章会分析其中的原因,并给出优化建议。
问题重现
在一个较复杂的项目中,我们使用了 Hapi 和 Mongoose 进行开发。其中,有一个需求需要进行多表查询,需要连接多个数据库表,并在其中筛选出符合条件的数据。我们最开始的实现如下(代码省略部分非关键代码):
----- ------ - ----- ------------- ---------- ---- ------------- ----- ------------ ------ - ----------- ---- -- ------- ----- --------- - ----- ------------------ ------- ---- -- -------------
这个查询逻辑并不复杂,但是在进行了一段时间后,我们发现查询时间非常长,而且当查询偏大时,查询效率更是堪忧。
我们想通过剖析代码确信没有什么明显的错误,并在不减少查询条件数量的情况下提高查询性能。
分析问题
在深入分析之前,我们想对 Mongoose 和数据库做一些简单介绍,以便更好地理解问题以及优化措施。
Mongoose
Mongoose 是一个优美的 Node.js MongoDB 模型驱动的对象模型,它使得在 Node.js 中处理 MongoDB 数据变得非常简单和顺畅。它不仅提供了简单而优雅的方式来执行 CRUD 操作,还提供轻松访问 MongoDB 数据库的多个功能。
相比于纯粹的 MongoDB 流行度,Mongoose 通常被选择为处理数据库时的 Node.js 首选。它将数据结构化成有意义的模型,并提供了从身份验证到查询优化的各种功能。
MongoDB
MongoDB 是一种基于分布式文件存储的数据库,由 C++ 编写。旨在为 Web 应用提供可扩展的高性能数据存储解决方案。
MongoDB 的重要特点包括:面向文档、模式自由、支持动态查询、支持完全索引、支持复制和故障恢复、使用高效的 BSON 存储数据。
既然你理解了 Mongoose 和 MongoDB,则很容易理解以下原则:
快速查询的关键在于在查询中使用索引。
问题原因
回到我们的查询逻辑,我们首先简单概述一下它的查询流程:
在使用
find
方法进行查询时,MongoDB 首先扫描索引,从符合条件的索引中获取文档 ID 数组。MongoDB 取得文档 ID 后,使用
_id
查询非索引字段或者其他值作为输入到下一阶段的过滤器。仅包含符合过滤器的文档。如果一个文档满足过滤器中的所有条件,则文档能够通过滤器。将对象返回给用户进行处理。
根据上述过程,我们可以预想到程序的性能开销在 _id
查询的耗时上。
查询性能下降原因有多种,但是在这里,我们简单地总结一些:
对于非索引字段上的过滤器查询时的缺失。
当我们的数据量变大时,查询会变得昂贵。
由于 join 或者深度数据嵌套检索时,在非索引字段上进行大量过滤,从而降低了效率。
在查询期间,如果需要对文件进行排序,它很可能涉及大量内存活动。
解决方案
到这里,我们可以开始考虑优化解决方案了。
对于第一种原因,我们需要了解优化 SQL 查询的方式,并将其应用到 Mongoose 查询中。
- 添加索引。请在查询字段上添加索引。
- 请避免查询非索引字段。当您在非索引字段上过滤时,这极大地影响了查询速度。
- 避免查询时显示所有数据。尽量使用
$project
限制返回字段。
对于第二种原因,我们可以使用另一个技巧来优化查询:
- 使用 skip 和 limit。定位到您想要的数据,并在那里切断查询。例如,归档旧数据也可以是有效的优化方案。
- 避免使用全集合扫描。如果您已经遍历了一个很长的集合,那么结果可能会很慢。此时,您可能需要使用更高级的聚合框架。
对于第三个原因,我们建议:
- 使用 Native Lookup 来实现 join。
利用 $lookup
,我们可以实现类似于 SQL JOIN 的操作。但是,在 Mongoose 中使用 $lookup
时,必须注意并避免使用非索引字段的 $match
。
----- ------ - ----- ------------------ - ------- - ---------- ---- - -- - -------- - ----- --------- ----------- ------ ------------- ------------ --- --- - -- - -------- - ----- --------- ----------- ------ ------------- ------------ --- --- - -- - --------- - ---------- -- -- - -------- - ------ ----- --- ---- ----- - ---- ----------------- ----- - - -- -- - -------- - ------ ----- --- ---- ----- - ---- ----------------- ----- - - - - -- - ------- -- - --
其中,我们使用多个 $lookup
进行 join,最后使用 $project
和 $filter
对于各个表格字段进行过滤。最后再使用 limit
方法限制查询数量,从而进行优化。
- 最后,对于第四个原因,请使用
$sort
和$skip
来限制排序和跳过。
结论
在本文中,我们讨论了使用 Hapi 和 Mongoose 进行开发时可能遇到的问题:在进行多表查询时遇到了性能问题。最后,我们提供了四种优化解决方案,包括:
在查询上使用索引,避免在非索引字段上进行大量过滤。
使用 skip 和 limit 等策略限制查询数量。
使用 Native Lookup 来实现 join,并使用
$project
和$filter
对于各个表格字段进行过滤。使用
$sort
和$skip
来限制排序和跳过。
为了使您的 Mongoose 应用程序性能更佳,您需要遵循最佳实践并不断调整您的应用程序。同时,我们也应该不断学习、思考。希望通过本文的分析和介绍,能够让大家了解和优化 Mongoose 查询的性能问题,并提升我们的开发能力和效率。
来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/64a4dd0948841e9894144ff6