当前位置:网站首页 / 数据库 / 正文

[AY-Mongo 3.x]写给自己的MongoDB笔记-索引[9]

时间:2015年11月06日 | 作者 : aaronyang | 分类 : 数据库 | 浏览: 1560次 | 评论 0

2015年11月9日      www.ayjs.net独家拥有,未经许可,不许转载,违者追究法律责任

废话不多说,一个索引就是为了更快地找到数据

for(var i=0;i<500000;i++){var ra=parseInt(i*Math.random());db.bigData.insert({"orderid":"ay"+ra,"number":i});}

插入50万条数据

blob.png

blob.png

等了还挺久的,将近1分钟,因为这里是我的错。。。。 我不应该每次insert插,而是应该先创建一个50万的json,然后一个insert

我先试下

var a=[];for(var i=0;i<500000;i++){var ra=parseInt(i*Math.random());a.push({"orderid":"ay"+ra,"number":i});}db.bigData.insert(a);

比刚才的快了13倍多,大约8秒

blob.png

Ok,现在这个集合有了100万条数据了。

blob.png


2015年11月9日      www.ayjs.net独家拥有,未经许可,不许转载,违者追究法律责任

查看存储引擎

blob.png

explain性能分析

db.bigData.find({"orderid":"ay10000"}).explain();

blob.png

这个跟以前的 2.x的mongo不一样,这是3.x的mongo,采用WiredTiger存储

stage 是COLLSCAN 说明没有走索引,走索引的话会显示 IXSCAN


默认索引

Default的索引是_id

单字段排序排序索引

除了默认的索引,mongo支持用户自己在单个字段上创建  升序或者降序的索引,为了方遍排序操作

db.bigData.createIndex( { "orderid" : 1 } )

创建一个 orderid升序的  索引,1大于0代表升序,小于0就是降序。

当然也支持嵌入式字段的 排序索引,这里数据没有模拟,我只是写下来,也很好理解

单列索引,随便你第一次升序还是降序,因为mongodb会自动切换排序方向

db.bigData.createIndex( { "orderid.cusid" : 1 } )

嵌入式文档,这是个嵌入式文档

{
  _id: ObjectId(...),
  metro: {
           city: "New York",
           state: "NY"
         },
  name: "Giant Factory"
}

创建db.factories.createIndex( { metro: 1 } )

查询db.factories.find( { metro: { city: "New York", state: "NY" } } )

嵌入的文档的字段顺序最好与文档一致,比如下面的不一致,就没有匹配到上面的结果

db.factories.find( { metro: { state: "NY", city: "New York" } }


组合索引(Compound Index)

组和的时候也跟顺序有关,比如

{ userid: 1, score: -1 }

就好比分组一样,先userid升序,然后 每组userid一样的,就score降序建立   排序索引

{
 "_id": ObjectId(...),
 "item": "Banana",
 "category": ["food", "produce", "grocery"],
 "location": "4th Street Store",
 "stock": 4,
 "type": "cases",
 "arrival": Date(...)
}
db.products.createIndex( { "item": 1, "stock": 1 } )

item升序,然后stock升序

如果你创建的字段拥有了hash索引,你可能会收到一个错误

。如果你创建了

db.events.createIndex( { "username" : 1, "date" : -1 } )

如果你想查询出来数据,下面这种是没有效果的,因为组合索引跟方向有关。

db.events.find().sort( { username: 1, date: 1 } )




创建一个索引

db.bigData.ensureIndex({"orderid":1})大约10秒吧

blob.png

db.bigData.find({"orderid":"ay10000"});

创建了索引后,这速度,100万数据,查询毫秒级别

31.gif



2015年11月9日      www.ayjs.net独家拥有,未经许可,不许转载,违者追究法律责任



唯一索引

创建db.bigData.ensureIndex({"orderid":1},{"unique":true})

因为这里面有重复的值,所以不能创建成功

blob.png

但是这里的错误是 orderid_1的这个名字已经有了,因为刚刚我们创建了索引


获得索引查看 db.bigData.getIndexes()

blob.png

这里的ns代表namespace


因为mongo查询优化器会优化,如果强制使用我们的查询方式去搜索,在mongodb中给我们提供了hint方法

比如组合索引,你2个顺序,那么mongo就有2个方案去 查询,你可以使用hint强制一个哪个方案执行

blob.png

这里的hint中的值,就是圈中的key后面的value

db.bigData.find({"orderid":"ay10000"}).hint({"orderid":1});

当然_id肯定慢点

db.bigData.find({"orderid":"ay10000"}).hint({"_id":1});

我们删掉索引,还是根据圈中的name属性删的

2.x的mongo貌似这样写的

db.bigData.dropIndexes("orderid_1")

3.x的mongo是

db.bigData.dropIndex("orderid_1")

blob.png



Multikey Index 多键索引

blob.png

如果你的索引列是数组,那么mongo就会为数组中的每一条节点创建一个索引。


测试组合件索引

插入数据

db.mukeyTest1.insert({ _id: 1, a: [ 1, 2 ], b: [ 1, 2 ], category: "AB - both arrays" });

blob.png

创建索引:

db.mukeyTest1.createIndex({a: 1,b: 1});

blob.png

multikey index不能同时两个都是数组,只能1个是数组。

比如下面数据就可以

{ _id: 1, a: [1, 2], b: 1, category: "A array" }
{ _id: 2, a: 1, b: [1, 2], category: "B array" }

多值索引

MongoDB可以对一个array类型创建索引,比如像下面的结构,MongoDB可以在tags字段上创建索引:

{ name: "Wheelbarrow",
tags: ["tools", "gardening", "soil"]
}

在生成索引时,会为tags中的三个值分别生成三个索引元素,索引中tools,gardening,soil三个值都会指向这同一行数据。相当于分裂成了三个独立的索引项

创建hash索引   

db.active.createIndex( { a: "hashed" } )

创建text索引

db.reviews.createIndex( { comments: "text" } )

一个集合做多一个text索引,类似mssql的全文索引

通配符text索引

db.collection.createIndex( { "$**": "text" } )
db.collection.createIndex( { a: 1, "$**": "text" } )

指定 text索引的语言

db.quotes.createIndex(
   { content : "text" },
   { default_language: "spanish" })

支持的语言

blob.png

多语言同时指定

db.quotes.createIndex( { quote : "text" },
                       { language_override: "idioma" } )

如果你的数据中一些行中没有某个字段或字段值为null,那么如果在这个字段上建立普通索引,那么无此字段或值null的行也会参与到索引结构中,占用相应的空间。如果我们不希望这些值为空的行参与到我们的索引中,这时候可以采用松散索引,松散索引只会让指定字段不为空的行参与到索引创建中来。创建一个松散索引可以用下面的命令:

db.reviews.ensureIndex({user_id: 1}, {sparse: true})

在后台创建索引

创建索引会对数据库添加写锁,如果数据集比如大,会将线上读写数据库的操作挂起,以等待索引创建结束。这影响了数据库的正常服务,我们可以通过在创建索引时加background:true 的选项,让创建工作在后台执行,这时候创建索引还是需要加写锁,但是这个写锁不会直接独占到索引创建完成,而是会暂停为其它读写操作让路,不至于造成严重的性能影响。具体方法:

db.values.ensureIndex({open: 1, close: 1}, {background: true})

离线创建索引

无论如何,索引的创建都会给数据库造成一定的压力,从而影响线上服务。如果希望创建索引的过程完全不影响线上服务,我们可以通过将replica sets中的节点先从集群中剥离,在这个节点上添加相应的索引,等索引添加完毕后再将其添加到replica sets中。这只需要保证一个条件,就是创建索引的时间不能长于oplog能够保存日志的时间,否则创建完后节点再上线发现再也无法追上primary了,这时会进行resync操作。

索引备份

我们知道,无论是使用mongodump还是mongoexport命令,都只是对数据进行备份,无法备份索引。我们在恢复的时候,还是需要等待漫长的索引创建过程。所以,如果你希望备份的时候带上索引,那么最好采用备份数据文件的方式。

索引压缩

索引在使用一段时间后,经历增删改等操作,会变得比较松散,从而战用不必要的空间,我们可以通过reindex命令,重新组织索引,让索引的空间占用变得更小。



还有几种索引这里不说了

2015年11月9日      www.ayjs.net独家拥有,未经许可,不许转载,违者追究法律责任

推荐您阅读更多有关于“mongodb,”的文章

猜你喜欢

额 本文暂时没人评论 来添加一个吧

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

  查看权限

抖音号:wpfui,可以看到我的很多作品效果

AYUI8社区版Github地址:前往获取

作者:杨洋(AaronYang简称AY,安徽六安人)目前是个人,还没公司AY唯一QQ:875556003和AY交流

高中学历,2015年1月17日开始,兴趣学习研究WPF

声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费.AY主要靠卖技术服务挣钱

不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo

查看捐赠

AYUI7.X MVC教程 更新如下:

第一课 第二课 程序加密教程

兼容XP到win10,vs2015/2019,最新AYUI:7.6.5.2

vs2015 企业版密钥HM6NR-QXX7C-DFW2Y-8B82K-WTYJV

vs2017 企业版密钥NJVYC-BMHX2-G77MM-4XJMR-6Q8QF

标签列表