设为首页 收藏本站
查看: 965|回复: 0

[经验分享] mongodb 索引问题的介绍

[复制链接]

尚未签到

发表于 2018-10-27 15:05:05 | 显示全部楼层 |阅读模式
索引类型
  虽然MongoDB的索引在存储结构上都是一样的,但是根据不同的应用层需求,还是分成了唯一索引(unique)、稀疏索引(sparse)、多值索引(multikey)等几种类型
  唯一索引
  唯一索引在创建时加上unique:true 的选项即可,创建命令如下:
  db.users.ensureIndex({username: 1}, {unique: true})
  上面的唯一索引创建后,如果insert一条username已经存在的数据,则会报如下的错误:
  E11000 duplicate key error index: gardening.users.$username_1 dup key: { : "kbanker" }
  如果你在一个已有数据的collection上创建唯一索引,若唯一索引对应的字段原来就有重复的数据项,那么创建会失败,我们需要加上一个dropDups的选项来强制将重复的项删除掉,命令如下例:
  db.users.ensureIndex({username: 1}, {unique: true, dropDups: true})
  松散索引
  如果你的数据中一些行中没有某个字段或字段值为null,那么如果在这个字段上建立普通索引,那么无此字段或值null的行也会参与到索引结构中,占用相应的空间。如果我们不希望这些值为空的行参与到我们的索引中,这时候可以采用松散索引,松散索引只会让指定字段不为空的行参与到索引创建中来。创建一个松散索引可以用下面的命令:
  db.reviews.ensureIndex({user_id: 1}, {sparse: true})
  多值索引
  MongoDB可以对一个array类型创建索引,比如像下面的结构,MongoDB可以在tags字段上创建索引:
  { name: "Wheelbarrow", tags: ["tools", "gardening", "soil"] }
  在生成索引时,会为tags中的三个值分别生成三个索引元素,索引中tools,gardening,soil三个值都会指向这同一行数据。相当于分裂成了三个独立的索引项。
  索引管理
  索引的创建和删除
  创建和删除索引的方法有很多种,下面两个是比较原始的方法,通过对system.indexes这个collection进行相应的写操作来完成索引的创建:
  

  
spec = {ns: "green.users", key: {‘addresses.zip’:1},name{‘zip’}db.system.indexes.insert(spec, true)
  

  上面命令往system.indexes中写入一条记录来创建索引,这条记录包含了要在上面创建索引的collection的名字空间,索引的信息,以及索引的名称。
  创建完成后,我们可以通过下面命令找到我们创建的索引:
  

  
db.system.indexes.find()
  
{ "_id" : ObjectId("4d2205c4051f853d46447e95"), "ns" : "green.users",
  
"key" : { "addresses.zip" : 1 }, "name" : "zip", "v" : 0 }
  

  要删除一个已创建的索引,我们可以使用下面的命令来实现:
  use green db.runCommand({deleteIndexes: "users", index: "zip"})
  创建索引命令
  实际上创建索引还有更方便的命令,那就是ensureIndex,比如我们创建一个open和close两个字段的联合索引,就可以用下面的命令:
  db.values.ensureIndex({open: 1, close: 1})
  这个命令会触发索引创建的两个过程,一个是将相应的字段排序,因为索引是按B+树来组织的,要构建树,将数据进行排序后能够提高插入B+树的效率(第二个过程的效率),在日志中,你能看到和下面类似的输出:
  

  
Tue Jan 4 09:58:17 [conn1] building new index on { open: 1.0, close: 1.0}forstocks.values
  
1000000/4308303 23%
  
2000000/4308303 46%
  
3000000/4308303 69%
  
4000000/4308303 92%
  
Tue Jan 4 09:59:13 [conn1] external sort used : 5 files in 55 secs
  

  第二个过程是将排序好的数据插入到索引结构中,构成可用的索引:
  

  
1200300/4308303 27%
  
2227900/4308303 51%
  
2837100/4308303 65%
  
3278100/4308303 76%
  
3783300/4308303 87%
  
4075500/4308303 94%
  
Tue Jan 4 10:00:16 [conn1] done building bottom layer, going to commit
  
Tue Jan 4 10:00:16 [conn1] done for 4308303 records 118.942secs
  
Tue Jan 4 10:00:16 [conn1] insert stocks.system.indexes 118942ms
  

  除了日志中的输出外,你还可以通过在终端执行currentOp命令来获取当前操作线程的相关信息,如下例:
  

  
> db.currentOp()
  
{
  
"inprog" : [
  
{
  
"opid" : 58,
  
"active" : true,
  
"lockType" : "write",
  
"waitingForLock" : false,
  
"secs_running" : 55,
  
"op" : "insert",
  
"ns" : "stocks.system.indexes",
  
"query" : {
  
},
  
"client" : "127.0.0.1:53421",
  
"desc" : "conn",
  
"msg" : "index: (1/3) external sort 3999999/4308303 92%"
  
}
  
]
  
}
  

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

  
db.values.ensureIndex({open: 1, close: 1}, {background: true})
  
离线创建索引
  

  无论如何,索引的创建都会给数据库造成一定的压力,从而影响线上服务。如果希望创建索引的过程完全不影响线上服务,我们可以通过将replica sets中的节点先从集群中剥离,在这个节点上添加相应的索引,等索引添加完毕后再将其添加到replica sets中。这只需要保证一个条件,就是创建索引的时间不能长于oplog能够保存日志的时间,否则创建完后节点再上线发现再也无法追上primary了,这时会进行resync操作。
  索引备份
  我们知道,无论是使用mongodump还是mongoexport命令,都只是对数据进行备份,无法备份索引。我们在恢复的时候,还是需要等待漫长的索引创建过程。所以,如果你希望备份的时候带上索引,那么最好采用备份数据文件的方式。
  索引压缩
  索引在使用一段时间后,经历增删改等操作,会变得比较松散,从而战用不必要的空间,我们可以通过reindex命令,重新组织索引,让索引的空间占用变得更小。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-627217-1-1.html 上篇帖子: mongodb 解决吃内存问题 下篇帖子: 记一次实验mongodb (save,insert )区别
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表