任何中间件的面试说到底都是以高可用、高性能和高并发为主,而高性能和高并发基本是同时存在的。
性能优化一直被看作一个高级面试点,因为只有对原理了解得很透彻的人,在实践中才能找准性能优化的关键点,从而通过各种优化手段解决性能问题
MongoDB查询过程
MongoDB在分片之后会有一些机制来保证查询能够准确找到数据。在分库分表中,查询的执行过程中最重要的一步,就是计算数据可能在哪个目标表上。如果实在计算不出来,那么只能考虑使用广播。
MongoDB也需要考虑类似的问题。在MongoDB里,有一类实例叫做mongos,这些实例负责路由查询到目标表上,还有合并结果集。
在分库分表中,计算目标表是分库分表中间件或分库分表代理完成的
MongoDB的ESR规则
在MongoDB里面设计索引的时候就要考虑所谓的ESR规则。
ESR代表的是E(Equality)、S(Sort)和R(Range),也就是相等、排序和范围。在设计索引的时候,按照ESR规则来排列你的索引列。
比如说,你用A进行等值查找,用B进行排序,用C进行范围查询,那么就应该是ABC,如果你是BAC,就违反了ESR规则。
而且ESR的三个元素是可以重复的,只要保证相对顺序不变就可以。
- EESR:两个等值列
- ESSR:两个排序列
- ER:没有排序列
- ERR:两个范围列
在设计、优化索引的时候就是要让索引尽量符合ESR规则。
面试准备
- 有没有遇到过MongoDB慢查询的问题?如果有,引发慢查询的原因是什么?最终是怎么解决的?
- 有没有优化过MongoDB的索引?是怎么优化的?
- MongoDB的参数有没有调整过?调过哪些?为什么调整?
- MongoDB的平均查询时间多长?99线以及999线是多少
你可以把 MongoDB 的性能优化、MySQL 查询性能优化、Elasticsearch 性能优化三个合并在一起。也就是说你整个面试思路就是讨论它们三个的性能优化手段。
比如:
- 在讨论到MySQL索引优化的时候,提起优化MongoDB的索引
- 在讨论到分库分表分页查询的时候,提起MongoDB里的mongos
- 在讨论Elasticsearch分片的时候,也可以提起MongoDB的分片
通过这样的横向对比,树立起一个掌握了各种中间件性能优化方法论的形象,从而加深面试官对你的印象,赢得竞争优势。
优化MongoDB查询
覆盖索引
在MySQL上使用覆盖索引的最大好处就是不需要回表,从索引里就可以直接拿到你需要的数据。
在MongoDB里也可以用这样的手段,也就是说,如果有一个索引上有你要查询的全部数据,那么MongoDB就不用把整个文档加载进来。最直观的做法就是在查询中使用projection
方法指定字段,而且这些字段都是索引字段。
这算是最基本的优化手段,在真实的工作场景也很常见,因为最开始开发者为了省事,通常是直接把所有的字段查询出来,后续随着数据量增长才会遇到性能问题。
之前我做过一个很简单的优化,早期有一个业务查询,就是把整个文档都加载进来。后面发现,这个查询的调用者大部分其实不需要整个文档,只需要里面的几个字段。所以就额外提供了一个新的查询接口,只会返回部分字段。优化后,大部分查询都是调用新接口,MongoDB也不需要把整个文档加载进来,性能提升了至少30%。
也可以进一步总结一下
不仅仅是查询,就算是在更新的时候,也要尽可能做到只更新必要的字段。比如在一些业务场景下,出于快速研发的角度,可能考虑前端把整个文档传过来,后端直接更新整个文档。但是如果只传修改过的字段,可以只更新必要的字段,这样的性能也很好。