练习 MongoDB 操作 —— 索引篇(二)

目录

  • Mongodb 索引篇(二)
  • 索引
    • 操作

      • 创建索引
      • 查看索引
      • 删除索引
    • 唯一索引
    • 稀疏索引
    • 性能示例
  • 游标

Mongodb 索引篇(二)

mongodb

更新于 2017-09-19 约 11 分钟
原文链接:https://segmentfault.com/a/1190000011263553

本文围绕索引、游标两部分进行探索,对MongoDB数据库的索引部分有一个大概的了解;

索引

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。

索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。索引,从创建的形式上可以分为普通索引复合索引数组索引子文档索引

应该了解的索引限制,

  • 开销:每个索引占据一定的存储空间,在进行插入,更新和删除操作时也需要对索引进行操作。所以,如果你很少对集合进行读取操作,建议不使用索引;
  • 内存(RAM)使用:由于索引是存储在内存中,你应该确保该索引的大小不超过内存的限制。如果索引的大小大于内存的限制,MongoDB会删除一些索引,这将导致性能下降。
  • 最大范围:
    (1)集合中索引不能超过 64 个;
    (2)索引名的长度不能超过 125 个字符;
    (3)一个复合索引最多可以有 31 个字段
  • 索引不能被以下的查询使用;可以调用explain()方法查看是否使用索引;
    (1)正则表达式及非操作符,如 `$nin`, `$not`, 等
    (2)算术运算符,如 `$mod` 等
    (3)`$where` 子句

操作

创建索引

为集合grade_1_4根据性别和年龄创建复合索引:

db.getCollection('grade_1_4').ensureIndex({"sex": 1, "age": 1})

会得到结果:

{
    "v" : 2,                  // 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本
    "key" : {
        "sex" : 1,
        "age" : 1
    },
    "name" : "sex_1_age_1",
    "ns" : "school.grade_1_4"
}

说明:基于sexage的查询将会用到该复合索引,或者是基于sex的查询也会用到该索引,但是只是基于age的查询将不会用到该复合索引。因此可以说,如果想用到复合索引,必须在查询条件中包含复合索引中的前N个索引列。然而如果查询条件中的键值顺序和复合索引中的创建顺序不一致的话,MongoDB可以智能的帮助我们调整该顺序,以便使复合索引可以为查询所用

如果分别为性别和年龄创建索引:

db.getCollection('grade_1_4').ensureIndex({"sex": 1})
db.getCollection('grade_1_4').ensureIndex({"age": 1})

会得到这样的结果:

{
    "v" : 2,
    "key" : {
        "sex" : 1
    },
    "name" : "sex_1",
    "ns" : "school.grade_1_4"
},
{
    "v" : 2,
    "key" : {
        "age" : 1
    },
    "name" : "age_1",
    "ns" : "school.grade_1_4"
}

查看索引

查看集合grade_1_4已经创建的索引规则:

db.getCollection('grade_1_4').getIndexes()

查看集合grade_1_4索引占用内存空间的大小,单位是字节:

db.getCollection('grade_1_4').totalIndexSize()

删除索引

删除集合grade_1_4namesex_1的索引规则:

db.getCollection('grade_1_4').dropIndex({"sex": 1})

唯一索引

创建唯一索引与普通索引的区别在于,多一个可选参数 unique;举个例子,根据姓名创建唯一索引:

db.getCollection('grade_1_4').ensureIndex({"name":1}, {"unique":true})

创建唯一索引能够保证每条记录的name字段值是不重复的;

当一个文档以唯一索引的方式保存到集合中去的时候,任何缺失的索引字段都会以null值代替,因此,不能在唯一索引上同时插入两条缺省的记录。

假设集合已经存在一些记录,在些基础上创建唯一索引;此时,对这些已经存在的记录,如果索引项值是存在重复的,则创建索引时会报错;如果一定要在这样的键上创建唯一索引,那么系统将保存第一条记录,剩下的记录会被删除,结合dropDups参数使用(此参数只能在mongodb 3.0版本之前使用):

db.getCollection('grade_1_4').ensureIndex({"name":1}, {unique:true, dropDups: true})

稀疏索引

稀疏索引的创建和完全索引的创建没有什么不同。使用稀疏索引进行查询的时候,某些由于缺失了字段的文档记录可能不会被返回,这是由于稀疏索引子返回被索引了的字段。

示例:

> db.people.ensureIndex({title:1},{sparse:true}) //在title字段上建立稀疏索引
> db.people.save({name:"Jim"})
> db.people.save({name:"yang",title:"prince"})
> db.people.find();
{ "_id" : ObjectId("4e244dc5cac1e3490b9033d7"), "name" : "Jim" }
{ "_id" : ObjectId("4e244debcac1e3490b9033d8"), "name" : "yang", "title" : "prince" }

> db.people.find().sort({title:1})//自有包含有索引字段的记录才被返回
{ "_id" : ObjectId("4e244debcac1e3490b9033d8"), "name" : "yang", "title" : "prince" }

> db.people.dropIndex({title:1})//删除稀疏索引之后,所有的记录均显示
{ "nIndexesWas" : 2, "ok" : 1 }

> db.people.find().sort({title:1})
{ "_id" : ObjectId("4e244dc5cac1e3490b9033d7"), "name" : "Jim" }
{ "_id" : ObjectId("4e244debcac1e3490b9033d8"), "name" : "yang", "title" : "prince" }

性能示例

创建三十万条数据

for (var i = 1; i <= 300000; i++) {
    db.getCollection('grade_1_5').insert({
       "name": "zhangsan" + i,
       "sex": Math.round(Math.random() * 10) % 2,
       "age": Math.round(Math.random() * 6) + 3
   });
}

根据姓名查一些特定的人

db.getCollection('grade_1_5').find(
    {
        $or: [{"name":"zhangsan10000"},{"name":"zhangsan14000"},{"name":"zhangsan9000"},{"name":"zhangsan23000"},{"name":"zhangsan24050"},
              {"name":"zhangsan12000"},{"name":"zhangsan14300"},{"name":"zhangsan9300"},{"name":"zhangsan23300"},{"name":"zhangsan24350"},
              {"name":"zhangsan11100"},{"name":"zhangsan15200"},{"name":"zhangsan8100"},{"name":"zhangsan22100"},{"name":"zhangsan26150"},
              {"name":"zhangsan10200"},{"name":"zhangsan14020"},{"name":"zhangsan9020"},{"name":"zhangsan23020"},{"name":"zhangsan24070"},
              {"name":"zhangsan10300"},{"name":"zhangsan14030"},{"name":"zhangsan9030"},{"name":"zhangsan23030"},{"name":"zhangsan24080"}]
    }
)

对姓名建立索引,会占用5873664字节

db.getCollection('grade_1_5').ensureIndex({"name": 1})

对于上面的命令,通过调整顺序,观察时间,对性能有一些大概的了解;

行为 创建-查询-建索引 创建-建索引-查询 建索引-创建-查询
创建时间 150.957s 150.957s 159.967s
查询时间 1.024s 0.005s 0.005s
建立索引时间 0.527s 0.527s 0.009s

游标

直接对一个集合调用find()方法时,我们会发现,如果查询结果超过二十条,只会返回二十条的结果,这是因为Mongodb会自动递归find()返回的是游标。

var cursor = db.getCollection('grade_1_4').find({});

执行上述命令时,shell并不会真正地访问数据库,而是等待开始要求获得结果的时候才向数据库发送查询请求。

此时可以对这个游标进行各种设置,然后调用游标的hashNext()next()方法,这样就会真正访问数据库,这是一个懒加载的过程,如下

var cursor = db.getCollection('grade_1_4').find({});

while(cursor.hasNext()){
    var doc = cursor.next();
    // do stuff with doc
};  

可以基于游标,进行limit、skip、sort操作,一般应用于分页场景;

  • limit:限制游标返回的数量,指定了上限;
  • skip :忽略前面的部分文档,如果文档总数量小于忽略的数量,则返回空集合;
  • sort :对得到的子集合进行排序,可以按照多个键进行正反排序;

上述三个命令可以进行链式操作;

文章来源于网络,仅用于学习,如有侵权,请联系删除。

原文地址:https://www.cnblogs.com/qzdd/p/12335630.html

时间: 2024-11-08 04:05:33

练习 MongoDB 操作 —— 索引篇(二)的相关文章

练习MongoDB 操作 — 备份篇(三)

mongodb3.x 发布于 2017-09-22 约 5 分钟 原文链接:https://segmentfault.com/a/1190000011263553 导入与导入 导入与导出是针对集合,对集合上的文档数据经过"查询条件"后导出: 导出 MongoDB的导出是利用mongoexport命令:同时列举常用的参数: -h:数据库宿主机的IP -u:数据库用户名 -p:数据库密码 -d:数据库名字 -c:集合的名字 -f:导出的列名 -q:导出数据的过滤条件 -o:导出文件的目录及

SQL Server 索引的图形界面操作 &lt;第十二篇&gt;

一.索引的图形界面操作 SQL Server非常强大的就是图形界面操作.关于索引方面也一样那么强大,很多操作比如说重建索引啊,查看各种统计信息啊,都能够通过图形界面快速查看和操作,下面来看看SQL Server索引方面的GUI操作. 二.索引统计信息的图形界面操作 SQL Server 索引的图形界面操作 <第十二篇>

MongoDB索引(一) --- 入门篇:学习使用MongoDB数据库索引

这个系列文章会分为两篇来写: 第一篇:入门篇,学习使用MongoDB数据库索引 第二篇:进阶篇,研究数据库索引原理--B/B+树的基本原理 1. 准备工作 在学习使用MongoDB数据库索引之前,有一些准备工作要做,之后的探索都是基于这些准备工作. 首先需要建立一个数据库和一些集合,这里我就选用一个国内手机号归属地的库,大约32W条记录,数据量不大,不过做一些基本的分析是够了. 首先我们建立一个数据库,叫做db_phone,然后导入测试数据.测试数据就是一些手机号归属地的信息.单个文档长这个样子

MongoDB入门学习(四):MongoDB的索引

上一篇讲到了MongoDB的基本操作增删查改,对于查询来说,必须按照我们的查询要求去集合中,并将查找到的结果返回,在这个过程中其实是对整个集合中每个文档进行了扫描,如果满足我们的要求就添加到结果集中最后返回.对于小集合来说,这个过程没什么,但是集合中数据很大的时候,进行表扫描是一个非常恐怖的事情,于是有了索引一说,索引是用来加速查询的,相当于书籍的目录,有了目录可以很精准的定位要查找内容的位置,从而减少无谓的查找. 1.索引的类型 创建索引可以是在单个字段上,也可以是在多个字段上,这个根据自己的

搭建高可用mongodb集群(二)—— 副本集

http://www.lanceyan.com/tech/mongodb/mongodb_repset1.html 在上一篇文章<搭建高可用MongoDB集群(一)——配置MongoDB> 提到了几个问题还没有解决. 主节点挂了能否自动切换连接?目前需要手工切换. 主节点的读写压力过大如何解决? 从节点每个上面的数据都是对数据库全量拷贝,从节点压力会不会过大? 数据压力大到机器支撑不了的时候能否做到自动扩展? 这篇文章看完这些问题就可以搞定了.NoSQL的产生就是为了解决大数据量.高扩展性.高

MongoDB学习笔记(二:入门环境配置及与关系型数据库区别总结)

一.下载及安装MongoDB MongoDB下载官网链接:http://www.mongodb.org/downloads 具体安装步骤教程:http://www.shouce.ren/api/view/a/6191(PS:该链接中对MongoDB安装讲解比较详细,通俗易懂.安装教程链接是我从手册网上找到的,下面的总结知识点也是本人从中学习后归纳的一部分,有兴趣的同学不妨收藏一下~) 二.MongoDB可视化工具下载 个人比较习惯在图形化界面进行相关命令操作,所以在安装完MongoDB后,就顺便

Mysql数据库优化技术之配置篇、索引篇 ( 必看 必看 转)

转自:Mysql数据库优化技术之配置篇.索引篇 ( 必看 必看 ) (一)减少数据库访问 对于可以静态化的页面,尽可能静态化 对一个动态页面中可以静态的局部,采用静态化 部分数据可以生成XML,或者文本文件形式保存 使用数据缓存技术,例如: MemCached (二)优化的检测方法 1.用户体验检测 2.Mysql状态检测 在Mysql命令行里面使用show status命令,得到当前mysql状态. 主要关注下列属性: key_read_requests (索引读的请求数)(key_buffe

MongoDB入门教程(二)

上一篇博文中,我详细描述了从MongoDB简介到安装,在本节,主要从整体角度去看MongoDB. MongoDB的数据架构 官方是这样描述的 MongoDB stores all documents in collections. A collection is a group of related documents that have a set of shared common indexes. Collections are analogous to a table in relatio

关于mongodb创建索引的一些经验总结

想来接触mongodb已经快一年了,对于它的索引知识也积攒了不少经验,趁着这个月黑风高的夜晚,就把mongodb的索引总结一番吧. 一,索引介绍 mongodb具有两类索引,分别为单键索引和复合索引. 1.单键索引是最简单的一种索引,创建单键索引的开销要比复合索引小很多.单键索引主要用于针对单值查询的条件. 2.复合索引是将文档中的几个键联合起来创建的一种索引,创建这种索引需要更多的空间与性能开销.分别体现在: 1).在给大量数据创建复合索引时,会阻塞数据库的查询,更不用说修改和插入操作了: 2