一、背景
Mongodb数据库,有个160w数据量规模的集合,字段多达几十个,随着需求的迭代,查询条件也是五花八门。
为了提高某个查询的效率,结果都以新增索引解决问题,最后多达16个索引。
这里仅贴出本文会提及的索引,可以看到,都是组合索引。
且不说索引越多,更新记录的时候会越耗时,查询想要匹配索引的时候却找不到想要的索引。
主要的害处是,一个查询语句不知道将会匹配哪个索引,既有单个索引,又有许多类似的组合索引。
本文主要是由一个慢查询语句抛出问题,先分析执行计划,然后给出优化建议。
二、定义mongodb集合和索引
字段名 | 类型 | 描述 | 示例 |
---|---|---|---|
createdOn | Date | 创建时间 | ISODate(“2024-04-28T00:00:00.000Z”) |
classroomName | String | 名称 | 英语期末考前复习课程 |
creatorName | String | 创建者名称 | 张三 |
totalIds | List | 人员集合 | [10001,10002,10003] |
isDelete | Boolean | 是否逻辑删除 | true/false |
recycle | int | 回收标记 | 0-未回收,1-已回收 |
auth | int | 公开标记 | 0-否,1-是 |
前后定义了16个索引,这里列出本文会涉及到的三个索引。
- createdOn_1_auth_1_isDelete_1_recycle_1_creatorName_1
- totalIds_1_isDelete_1_recycle_1_creatorName_1
- totalIds_1_createdOn_2
三、慢查询分析
从阿里云Mongodb的慢日志,找到是哪个慢语句。
找到command命令,见下:
{
"$and":[{
"$and":[{
"$and":[{
"isDelete":false},
{
"$or":[{
"auth":1},{
"totalIds":{
"$in":[10001]}}]},
{
"$or":[{
"recycle":null},{
"recycle":0}]}],
"classroomName":{
"$regex":".*大口加小口.*","$options":""}},
{
"createdOn":{
"$gte":{
"$date":"2023-04-29T00:00:00.000+0800"}}}]},
{
"createdOn":{
"$lte":{
"$date":"2024-04-30T00:00:00.000+0800"}}}]},
"projection":{
"$sortKey":{
"$meta":"sortKey"}},
"sort":{
"createdOn":-1},
"limit":{
"$numberLong":"20"}
解析下这个查询语句的业务需求:
用户10001查询近一年的公开课或自己的课程,查询条件是课程名称正则匹配。(另外必须是未删除且未被放入回收站的课程)
1、真实的查询语句
db.{
集合名}.find(
{
"$and": [
{
"$and": [
{
"isDelete": false },
{
"$or": [
{
"auth"