MongoDB数据库索引基础知识与实战技巧

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介:

本文内容源自Kyle Banker 的MongoDB In Action一书。主要描述了MongoDB索引相关的一些基础知识和使用技巧。

  索引类型

  虽然MongoDB的索引在存储结构上都是一样的,但是根据不同的应用层需求,还是分成了唯一索引(unique)、稀疏索引(sparse)、多值索引(multikey)等几种类型。

  1.唯一索引

  唯一索引在创建时加上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})
2.松散索引

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

  db.reviews.ensureIndex({user_id: 1}, {sparse: true})
3.多值索引

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

  { name: "Wheelbarrow",

  tags: ["tools", "gardening", "soil"]

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

  索引管理

  1.索引的创建和删除

  创建和删除索引的方法有很多种,下面两个是比较原始的方法,通过对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"})
2.创建索引命令

  实际上创建索引还有更方便的命令,那就是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 } for stocks.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%。

  3.在后台创建索引

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

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

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

  索引备份

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

  索引压缩

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










本文转自 wws5201985 51CTO博客,原文链接:http://blog.51cto.com/wws5201985/773843,如需转载请自行联系原作者
相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
6天前
|
存储 JSON NoSQL
学习 MongoDB:打开强大的数据库技术大门
MongoDB 是一个基于分布式文件存储的文档数据库,由 C++ 编写,旨在为 Web 应用提供可扩展的高性能数据存储解决方案。它与 MySQL 类似,但使用文档结构而非表结构。核心概念包括:数据库(Database)、集合(Collection)、文档(Document)和字段(Field)。MongoDB 使用 BSON 格式存储数据,支持多种数据类型,如字符串、整数、数组等,并通过二进制编码实现高效存储和传输。BSON 文档结构类似 JSON,但更紧凑,适合网络传输。
31 15
|
14天前
|
存储 NoSQL 关系型数据库
阿里云数据库MongoDB版助力信也科技 打造互联网金融企业样板
我们的风控系统引入阿里云数据库MongoDB版后,解决了特征类字段灵活加减的问题,大大提高了开发效率,极大的提升了业务用户体验,获得了非常好的效果
阿里云数据库MongoDB版助力信也科技 打造互联网金融企业样板
|
22天前
|
存储 缓存 数据库
数据库索引采用B+树不采用B树的原因?
B+树优化了数据存储和查询效率,数据仅存于叶子节点,便于区间查询和遍历,磁盘读写成本低,查询效率稳定,特别适合数据库索引及范围查询。
36 6
|
1月前
|
存储 NoSQL 关系型数据库
MongoDB索引知识
MongoDB索引知识
31 1
MongoDB索引知识
|
1月前
|
存储 缓存 数据库
数据库索引采用B+树不采用B树的原因
B+树相较于B树,在数据存储、磁盘读写、查询效率及范围查询方面更具优势。数据仅存于叶子节点,便于高效遍历和区间查询;内部节点不含数据,提高缓存命中率;查询路径固定,效率稳定;特别适合数据库索引使用。
29 1
|
1月前
|
数据库 索引
数据库索引
数据库索引 1、索引:建立在表一列或多列的辅助对象,目的是加快访问表的数据。 2、索引的优点: (1)、创建唯一性索引,可以确保数据的唯一性; (2)、大大加快数据检索速度; (3)、加速表与表之间的连接; (4)、在查询过程中,使用优化隐藏器,提高系统性能。 3、索引的缺点: (1)、创建和维护索引需要耗费时间,随数据量增加而增加; (2)、索引占用物理空间; (3)、对表的数据进行增删改时,索引需要动态维护,降低了数据的维护速度。
37 2
|
1月前
|
存储 SQL 数据库
深入浅出后端开发之数据库优化实战
【10月更文挑战第35天】在软件开发的世界里,数据库性能直接关系到应用的响应速度和用户体验。本文将带你了解如何通过合理的索引设计、查询优化以及恰当的数据存储策略来提升数据库性能。我们将一起探索这些技巧背后的原理,并通过实际案例感受优化带来的显著效果。
49 4
|
1月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
283 1
|
1月前
|
存储 关系型数据库 数据库
Postgres数据库BRIN索引介绍
BRIN索引是PostgreSQL提供的一种高效、轻量级的索引类型,特别适用于大规模、顺序数据的范围查询。通过存储数据块的摘要信息,BRIN索引在降低存储和维护成本的同时,提供了良好的查询性能。然而,其适用场景有限,不适合随机数据分布或频繁更新的场景。在选择索引类型时,需根据数据特性和查询需求进行权衡。希望本文对你理解和使用PostgreSQL的BRIN索引有所帮助。
53 0
|
JSON NoSQL Java
mongoDB导出数据库所有集合内容到json文件
网上搜了一圈,官方并有提供批量导出所有集合到json文件的方法。有不少脚本可以实现,但是我还是习惯用java,如下 package starcLL.
2224 0