首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个数组查询引发的坑

一个数组查询引发的坑

作者头像
MongoDB中文社区
发布2019-04-22 15:26:08
7800
发布2019-04-22 15:26:08
举报
文章被收录于专栏:MongoDB中文社区MongoDB中文社区

背景

中午12点半,接到了线上MongoDB 数据库异常的告警通报:

“CPU不间断飙升到百分百,业务也相应出现了抖动现象。”

通过排查数据库主节点的日志,发现了这样的一个慢语句:

从语句中初步判断,“keysExamined”和docsExamined 显示扫描了100W 条记录,其中也用到了下面的索引:

跟研发兄弟确认过后,该查询的目的是 找到某些应用下带指定标签的设备信息,按ID分段去获取,每次只查询10条。

关于索引的设计也已经确认过是最优的了,而且此前在开发环境中一直没有出现过问题,不知道为什么这次就出问题了。

详细分析

接下来,看了下该集合的模型,大致是长下面的样子:

说明 除了其他的属性之外,tags字段采用了嵌套文档数组的结构; 每一个元素都对应了一个tag对象,包含 tagName/tagValue/tagType几个字段。

然后是查询的模式

这从索引的前缀匹配来看,是应该没有问题的,索引的定义如下所示:

为了避免对线上环境造成影响,我们找了一个测试环境来做了尝试复现,执行:

结果却跟线上的情况不大一样,这次选中的是_id索引!

而同样的是也扫描了100W+的记录数,于是大家认为可能索引的选择器出了问题,但就算是选择器的问题也仍然没办法解释线上出现的现象(线上的索引可是命中的)

为了一探究竟,我们使用 hint 强制让查询命中 appId_1_tags.tagName_1_tags.tagValue_1__id_1这个索引:

这一次的结果显示确实命中了对应的索引:

然而,在整个执行过程中(executionStats),出现了内存排序(SORT)。

而且,从一开始命中** appId_1_tags.tagName_1_tags.tagValue_1__id_1 **这个索引的阶段中,就已经扫描了100W条记录,简直不可思议!

但同时,我们也从indexBounds的指示中找到了端倪:

appId、tags.tagName 都命中了单值,在 tags.tagValue 的路径节点上却覆盖了全部范围!

由于中间索引节点出现了大范围覆盖,导致最终需要在内存中对大量的数据做 _id字段的排序,这个就是导致慢操作的原因!

解决问题

既然从前面的分析中找到了问题的来源,我们的推论如下:

既然索引的命中没有问题,那么导致大范围扫描的只可能是查询模式的问题。

再次拿出前面的查询条件:

在索引的匹配中,只能单键命中tags.tagName: “pipeline” 这一个条件,那么由于 tags是一个嵌套文档的数组, 对于上面的查询,语义上是指那些 包含某个元素 可命中tagName,且包含某个元素 可命中 tagValue的文档,这里面并不要求 同一个元素同时命中tagName和tagValue。

但 MongoDB 在嵌套数组索引的构建上是按照同一个元素的字段组合去构建的。 关于这点,可以参考下面的地址:

https://docs.mongodb.com/manual/core/index-multikey/#multikey-embedded-documents

对于数组元素的条件匹配,应该使用 $elemMatch,其用法可参考这里

为此,我们构建了下面的查询:

执行后输出如下:

这个结果是令人满意的,除了自动命中合适的索引之外,这个查询过程也达到了最优的路径匹配,扫描记录数才10条!

最后,根据该方案调整了查询模式,线上的问题得到恢复。

小结

看似很简单的一个查询语句,没想到会出现这么大的坑,其实无论是作为开发人员还是DBA,都应当谨慎对待你的SQL。

重要的事情说三遍!!! SQl查询上线前务必 explain、务必分析到位,这难道没有道理?

作者

唐卓章

华为技术专家,多年互联网研发/架设经验,关注NOSQL 中间件高可用及弹性扩展,在分布式系统架构性能优化方面有丰富的实践经验,目前从事物联网平台研发工作,致力于打造大容量高可用的物联网服务。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Mongoing中文社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档