文档章节

mongodb 的查询如何使用索引

巡山
 巡山
发布于 2016/04/10 18:44
字数 875
阅读 26
收藏 0

一、准备

        需要在mongodb中添加测试数据

db.user.insert({"name":"张三","age":34,"job":"java 开发","phone":"18989834028","addr":"广东深圳福田"})
db.user.insert({"name":"李四","age":29,"job":"php 开发","phone":"18984834098","addr":"广东深圳南山"})
db.user.insert({"name":"王五","age":38,"job":"部门经理","phone":"18981834098","addr":"广东深圳罗湖"})
db.user.insert({"name":"赵一","age":31,"job":"产品经理","phone":"18989764098","addr":"广东广州"})
db.user.insert({"name":"钱二","age":26,"job":"销售","phone":"18989834968","addr":"广东珠海"})
db.user.insert({"name":"周六","age":54,"job":"销售经理","phone":"18981234098","addr":"广东中山"})
db.user.insert({"name":"吴奇","age":17,"job":"学生","phone":"18735834098","addr":"广东韶关"})
db.user.insert({"name":"郑八","age":45,"job":"教师","phone":"18989834098","addr":"广东惠州"})
db.user.insert({"name":"冯峰","age":23,"job":"java 开发","phone":"13689834098","addr":"广东广州越秀"})

          我们知道使用mongodb objectId数据主键_id是默认有索引的。下面先按名称和手机创建单独的索引,然后创建一个联合主键

db.user.ensureIndex({"phone":1});
db.user.ensureIndex({"name":1});
db.user.ensureIndex({"name":1,"phone":1});

          查看下现在已有的索引

>db.user.getIndexes();
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "test.user"
        },
        {
                "v" : 1,
                "key" : {
                        "name" : 1
                },
                "name" : "name_1",
                "ns" : "test.user"
        },
        {
                "v" : 1,
                "key" : {
                        "phone" : 1
                },
                "name" : "phone_1",
                "ns" : "test.user"
        },
        {
                "v" : 1,
                "key" : {
                        "name" : 1,
                        "phone" : 1
                },
                "name" : "name_1_phone_1",
                "ns" : "test.user"
        }
]

二、测试

       使用explain()方法查看执行计划,首先看下不使用查询条件。

> db.user.find().explain();
{
        "queryPlanner" : {
                  "winningPlan" : {
                        "stage" : "COLLSCAN",
  
}

           可以看到没有使用查询条件的情况下使用的是全表扫描。

           再来看下根据name,和phone作为查询条件的情况下,使用的是联合索引,还是单独的索引。

> db.user.find({"phone":"13678763456","name":"李斯"}).explain();
{
        "queryPlanner" : {
                  "winningPlan" : {
                                "indexName" : "name_1",                           
                },
                "rejectedPlans" : [
                     {
                                        "indexName" : "name_1_phone_1",
                                        ....                                      
                                }
                        },
                        {
.....
                                        "indexName" : "phone_1",
                                       ......                                       
                                }
                        }
                ]
        },
}

         可以看到,并没有使用联合主键并没有在最优计划(winningPlan)中,而是在rejectedplan中。先使用了phone的单独索引。调整查询条件顺序,索引的顺序是name,phone,看下

> db.user.find({"name":"李斯","phone":"18737260965"}).explain();
{
        "queryPlanner" : {
            ....
                "winningPlan" : {
                       ......
                        "inputStage" : {
                               .......
                                "indexName" : "name_1",
                             ......                            
                        }
                },
                "rejectedPlans" : [
                        {
                                "inputStage" : {
                                      .........
                                        "indexName" : "name_1_phone_1",
                                      ........
                                     
                        },
                        {    
                                "inputStage" : {                                      
                                        "indexName" : "phone_1",
                                      .......                                    
                        }
                ]
        },

}

        调整顺序之后还是一样,在winningPlan使用name的单独索引而不是联合索引。删除单独的索引再测试

db.user.dropIndex("name_1");
db.user.dropIndex("phone_1");

   测试

> db.user.find({"name":"李斯","phone":"18737260965"}).explain();
....
 "winningPlan" : {                       
                       ...
                                "indexName" : "name_1_phone_1",
                                ...
                                
                 
> db.user.find({"phone":"13678763456","name":"李斯"}).explain();
  "winningPlan" : {
                       .....
                                "indexName" : "name_1_phone_1",
                                ....
> db.user.find({"phone":"13678763456","name":"李斯","age":23}).explain();
  "winningPlan" : {
  。。。
 "indexName" : "name_1_phone_1",
 
> db.user.find({"phone":"13678763456","age":23,"name":"李斯"}).explain();

 "winningPlan" : {
      "indexName" : "name_1_phone_1",
      
> db.user.find({"phone":"13678763456"}).explain();
 "winningPlan" : {
                        "stage" : "COLLSCAN",
                        
> db.user.find({"name":"张三"}).explain();
  "winningPlan" : {
。。。。
                                "indexName" : "name_1_phone_1",
                                
> db.user.find({"age":33,"name":"张三"}).explain();
 "winningPlan" : {
                     。。。。
                                "indexName" : "name_1_phone_1",

     可以看到对于联合索引,如果只使用一部分,则必须是按顺序的(在本测试中只用使用name才用到索引),如果满足条件(name,phone 都出现在条件中),则没有顺序要求。

   三、终结

          通过简单的测试,对mongodb( "version" : "3.2.4",)的索引工作原理理解:

               1、如果某个字段同时出现在单独索引和联合索引中,winningPlan 使用的是单独索引。

               2、如果查询条件满足索引的条件,则不需要管理条件字段顺序,

               3、如果查询条件字段不满足联合索引,则必须是按创建索引的字段顺序查询才会使用索引。(可以有其他字段在索引字段前如,{"age":33,"name":"张三"}).

© 著作权归作者所有

巡山
粉丝 2
博文 20
码字总数 12425
作品 0
深圳
私信 提问
基于云数据库MongoDB版进行应用开发

MongoDB是一个基于分布式文件存储的数据库,在互联网、物联网、游戏、金融等领域被广泛采用。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是当前最流行的Nosql...

mcy0425
2018/09/14
0
0
探索 MongoDB

在本文中,您将了解 MongoDB ,这是一个开放源码、面向文档的数据库,使用 C++ 语言编写,它的特点是能够在生产环境随意扩展数据库。探索面向文档的数据库相比传统关系型数据库管理系统 (RDB...

IBMdW
2011/09/01
3.2K
3
云MongoDB优化让LBS服务性能提升十倍

欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 随着国内服务共享化的热潮普及,共享单车,共享雨伞,共享充电宝等各种服务如雨后春笋,随之而来的LBS服务定位问题成为了后端...

腾讯云开发者社区
2017/09/26
0
0
是时候跟 MongoDB 说再见了

在过去的两到三年的时间内,我一直在一个中等规模的项目中使用 MongoDB。 但因为各种技术上的原因,到了和 MongoDB 说再见的时候了,我的原因有以下几点: MongoDB 当前的内存模型基于内存映...

oschina
2012/05/20
21.5K
59
mongoDB 学习笔记纯干货(mongoose、增删改查、聚合、索引、等等)

最后更新时间:2017-07-13 11:10:49 原始文章链接:http://www.lovebxm.com/2017/07/13/mongodb_primer/ MongoDB - 简介 官网:https://www.mongodb.com/ MongoDB 是一个基于分布式文件存储的...

Airship
2018/06/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如何使用 rsync 备份 Linux 系统的一些介绍

备份一直是 Linux 世界的热门话题。回到 2017,David Both 为 Opensource.com 的读者在使用 rsync 备份 Linux 系统方面提了一些建议,在这年的更早时候,他发起了一项问卷调查询问大家,在 ...

Linux就该这么学
30分钟前
2
0
以太坊私有链搭建

https://blog.csdn.net/Blockchain_lemon/article/details/80589123

Moks角木
今天
3
0
自律给我自信-为什么要自律

为什么要自律 混一天和努力一天 看不到任何差别 3天看不到任何变化 7天也看不到任何效果 但是 1个月后, 会看到话题不同 3个月后, 会看到气场不同 6个月后, 会看到距离不同 3年后, 会看到...

周大壮
今天
4
0
读书replay计划说明

突然脑袋一闪,我有了这样一个主意:通过写博客的方式,将我阅读的书中的内容replay出来。 我一般会找着我感兴趣的书去读,一般也会读书中我感兴趣的章节,或者当下对我有用的章节,所以这个...

wanxiangming
今天
1
0
CentOS7安装xrdp环境可实现远程桌面访问

CentOS7安装xrdp环境可实现远程桌面访问 2018-07-14 06:39:28 分类:运维 阅读(2051) 评论(0) 在"Ubuntu系统安装xrdp桌面客户端及实现远程连接桌面"文章中有分享过在Ubuntu系统中安装XRDP环境...

linjin200
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部