本文主要讨论 “mongodb的索引” 和 “查询结果的排序” 之间的关系,索引对排序有什么影响,为什么有影响,应该遵循什么规则。

1. 先从创建单字段索引,认识“索引排序”:

db.集合名.createIndex(要给哪一列创建索引 [,额外选项]);

第1个参数是 “给哪一列创建索引”,它的格式是: {key:1或-1},其中1表示升序,-1表示降序。

第2个参数是 “额外选项”,它是可选的,比如:设置索引名称、指定索引类型等等。

举例: db.集合名.createIndex({age:1}) ;  —> 表示在age字段上创建索引并按照升序的方式存储索引数据。

注意:索引也是一堆数据,索引是一些按照指定规则排序的数据, 最终也是被存储起来的, 也是占用磁盘空间的。

所以,在创建索引的时候要指定一个存储顺序(1升序, -1降序) ,告诉它是升序存储还是降序存储。

2. 给索引数据排序,意义何在 ?

在MongoDB中,排序操作,可以通过从索引中按照索引的顺序获取文档的方式,来保证结果的有序性。

如果MongoDB的查询计划器(planner) 没法从索引中得到排序顺序,那么它就需要在内存中对结果排序。

相比于“不用索引的排序”操作,用索引会有更好的性能。

注意,关键是:不用索引的排序操作,会在用了超过32MB内存时终止,也就是说MongoDB只能支持32MB的非索引排序 。

如果数据量很大,比如我目前的应用场景下,都是千万级数据量,而且飞速增加,达亿级……

3. 用索引对查询结果进行排序

索引,是以升序(1) 或 降序(-1) 的排序顺序,存储对字段的引用。

单字段索引的排序

如果在单字段上是升序索引或降序索引,则对该字段的排序操作可以是任一方向。

例如:在集合records的a字段上创建一个升序索引:db.records.createIndex( { a: 1 } ) ;

上面的索引可以支持在 a 字段上的升序排序:db.records.find().sort( { a: 1 } ) ;

上面是索引还可以通过按相反的顺序遍历索引,来支持在 a 字段上的降序排序:db.records.find().sort( { a: -1 } ) ;

对于单字段索引,字段的排序顺序并不重要,因为MongoDB可以在任意方向遍历索引。

但是,对于复合索引,排序顺序在确定索引是否支持排序操作时很重要。

复合索引的排序

你可以指定在索引的所有字段或者部分字段上排序。

用复合索引排序时,sort() 中所指定的排序字段有以下两点需要遵循,否则不会走索引排序:

(1)排序字段的 “排列顺序”,必须和它们在索引中的排列顺序一致。

划重点:前后顺序,必须一致。

例如,索引 { a: 1, b: 1 } ,可以支持 { a: 1, b: 1 } 上的排序,但不支持 { b: 1, a: 1 } 上的排序。

(2)排序字段的 “排序顺序”,必须和索引中的对应字段的排序顺序完全相同或完全相反。

划重点:升降序顺序,要么完全一样、要么完全相反。

例如,索引 { a: 1, b: -1 } ,可以支持 { a: 1, b: -1 }  和  { a: -1, b: 1 }  的排序,但不支持 { a: -1, b: -1 } 或 { a: 1, b: 1 } 的排序。

实例:events集合中包含username和date字段,建立复合索引 db.events.createIndex( { "username" : 1, "date" : -1 } ) ,它可以支持下面两种排序操作:

db.events.find().sort( { username: 1, date: -1 } ) 先按username升序再按date降序,它和索引字段的升降序顺序完全一样

db.events.find().sort( { username: -1, date: 1 } ) 先按username降序再按date升序,它和索引字段的升降序顺序完全相反

上面的索引不支持 db.events.find().sort( { username: 1, date: 1 } ) 先按username升序再按date升序的排序,因为它和索引字段的升降序顺序 既不完全一样、也不完全相反

4. 排序与索引前缀

如果“排序字段”能和“索引字段或索引前缀”对应起来,那MongoDB就可以使用索引来对查询结果进行排序。

复合索引的前缀是指被索引字段的子集,它由一个或多个排在最开始的字段组成。

例如,在集合 data 上创建一个复合索引:db.data.createIndex( { a:1, b: 1, c: 1, d: 1 } )  那么这个索引的前缀如下:

{ a: 1 }

{ a: 1, b: 1 }

{ a: 1, b: 1, c: 1 }

下面的查询和排序操作,都可以使用索引前缀来排序查询结果。

也就是说下面这些操作都不需要在内存中对结果集排序。

例子

索引前缀

db.data.find().sort( { a: 1 } ) { a: 1 }
db.data.find().sort( { a: -1 } ) { a: 1 }
db.data.find().sort( { a: 1, b: 1 } ) { a: 1, b: 1 }
db.data.find().sort( { a: -1, b: -1 } ) { a: 1, b: 1 }
db.data.find().sort( { a: 1, b: 1, c: 1 } ) { a: 1, b: 1, c: 1 }
db.data.find( { a: { $gt: 4 } } ).sort( { a: 1, b: 1 } ) { a: 1, b: 1 }

索引也支持使用非前缀字段来排序。

不过这种情况是有前提的,就是:查询语句中 必须 把排序字段之前的所有前缀字段,都加上相等条件。

例如,集合 data 有 { a: 1, b: 1, c: 1, d: 1 } 索引,如下操作可以使用索引来排序:

例子

索引前缀

db.data.find( { a: 5 } ).sort( { b: 1, c: 1 } ) { a: 1 , b: 1, c: 1 }
db.data.find( { b: 3, a: 4 } ).sort( { c: 1 } ) { a: 1, b: 1, c: 1 }
db.data.find( { a: 5, b: { $lt: 3} } ).sort( { b: 1 } ) { a: 1, b: 1 }

如最后一个操作所示,只有索引中那些排列在排序字段前面的字段,必须在查询语句中有相等匹配条件,其他的索引字段才可以指定其他匹配条件。

如果查询语句 没有 对排列在排序字段前面 或 与之有所重叠的前缀字段指定相等匹配条件,那么操作将 不会 走索引。

例如,如下操作指定了排序 { c: 1 } ,但是查询语句并没有对前缀字段 a 和 b 指定相等匹配:

db.data.find( { a: { $gt: 2 } } ).sort( { c: 1 } ) ;

db.data.find( { c: 5 } ).sort( { c: 1 } ) ;

这些操作不会走索引 { a: 1, b: 1, c: 1, d: 1 } ,甚至可能不用索引检索文档。

Mongodb 索引 对查询结果的排序相关推荐

  1. Mongodb索引和执行计划 hint 慢查询

    查询索引 索引存放在system.indexes集合中 > show tables address data person system.indexes 默认会为所有的ID建上索引 而且无法删除 ...

  2. mongodb索引--1亿条记录的查询从55.7秒到毫秒级别补充版

    从头开始,验证mongodb的索引的好处.(window7环境下) 下载mongodb服务器,并解压到d盘,并使用以下命令启动 mongod --dbpath D:\mongodb\data mong ...

  3. 学习 | MongoDB 索引和排序

    小小又开始学习了,这次学习的内容是索引和排序. 索引 先给users集合插入两条记录,然后用users集合来进行索引管理的演示: > user1={"name":" ...

  4. mongodb索引生成HTML页面,mongodb高阶:索引创建、聚合查询、复制集、分片、创建备份和部署...

    先前我们讨论了mongodb的进阶查询:投影查询.分页查询以及对查询结果进行排序,从本节起我们开始学习mongodb相关的高级技术,首先我们会讨论mongodb如何创建索引,索引是数据库中最重要的东西 ...

  5. MongoDB 索引

    2019独角兽企业重金招聘Python工程师标准>>> 索引Indexes 索引常常用来大幅度的提升查询的性能. 考虑应用程序的查询种类是非常重要的事情,因此你就要定义相关的索引. ...

  6. MongoDB · 引擎特性 · MongoDB索引原理

    MongoDB · 引擎特性 · MongoDB索引原理 数据库内核月报 原文链接 http://mysql.taobao.org/monthly/2018/09/06/ 为什么需要索引? 当你抱怨M ...

  7. MongoDB 进阶-关联查询

    [苏州需要工作的加我QQ,内推介绍费平分] MongoDB 进阶 1.数据库命令 a.命令的工作原理 drop命令,在shell中删除一个集合,执行db.refactor.drop().其实这个函数实 ...

  8. mysql使用索引为什么查询速度变快很多?

    来源:http://www.2cto.com/database/201607/530931.html 首先来看看表是否有索引的命令 show index from 表名: 看到主键索引,索引类型是BT ...

  9. MongoDB 索引-9

    MongoDB 索引 索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录. 这种扫描全集合的查询效率是非常低的,特别在处理大 ...

最新文章

  1. 面试常考,项目易错,长文详解C/C++中的字节对齐
  2. 《Genesis-3D游戏引擎系列教程-进阶篇》6:动画
  3. Android-02:使用SharedPreferences存储简单数据
  4. 精选30张炫酷的动态交互式图表,Pandas一键生成,通俗易懂
  5. HDU Problem - 5935 Car(模拟)
  6. 19 删除链表的倒数第N个
  7. 万字长文!Unix和Linux你不知道的那些历史(详解版)
  8. Struts2——(3)ValueStack(值栈)
  9. 【ZOJ 1964】【尺取】Bound Found【暑期 No.3】
  10. 整理15款实用javascript富文本编辑器 转自136go
  11. 晋南讲堂之持久层框架ORM简介
  12. dw网页制作的基本步骤_dreamweaver制作网页详细步骤(设计网站首页)
  13. Ubuntu总是默认进入客人会话问题解决
  14. 输入年份 计算 生肖 C语言实现
  15. 交叉电缆与以太网电缆有哪些区别之处,弱电工程师必知!
  16. Apache安全漏洞
  17. pycharm 2017.3破解方法
  18. Tab页面知识整理及其方法分析
  19. 加密算法学习(一、中、1)——传统加密算法(playfair密码)
  20. font-family可以设置的字体

热门文章

  1. 健身教练演示背阔肌锻炼方法动作图解
  2. index.dat文件剖析(转)
  3. 零点城市社交电商 2.1.7.4 独立版 全开源 含前后端VUE文件 全插件
  4. dilink智能网联系统鸿蒙系统,Dilink3.0系统,它不只是当下最容易上手的智能网联系统...
  5. svn: E170001
  6. linux svn 提交 认证失败 170001
  7. 月经贴——.net前景何妨!
  8. 帝国竞争算法(ICA)详解与python 实现
  9. 莆田学院计算机在哪个校区,莆田学院有几个校区
  10. 2021 电子科技大学 组合数学试卷 (卢光辉、戴波 )