转载请出自出处:http://eksliang.iteye.com/blog/2178555
一、概述
上一篇文档中也说明了,MongoDB的索引几乎与关系型数据库的索引一模一样,优化关系型数据库的技巧通用适合MongoDB,所有这里只讲MongoDB需要注意的地方
二、索引内嵌文档
可以在嵌套文档的键上建立索引,方式与正常的键一样。如果有这样一个集合,如下所示:
db.emp.insert({ "_id":"A001", "name":{ "first":"Carey", "last":"Ickes" }, "age":25 })
现在我要在内嵌文档的first键上建立索引?如下所示
> db.emp.ensureIndex({"name.first":1})
温馨提示:对嵌套文档本身“name”建立索引,与对嵌套文档的某个字段(name.first)建立索引是完全不相同的,对整个文档建立索引,只有在使用文档完整匹配时才会使用到这个索引,例如建立了这样一个索引db.emp.ensureIndex({"name":1}),那么只有使用db.emp.find({"name":{"first":"xxx","last":"xxx"}})这种完整匹配时才会使用到这个索引,使用db.emp.find({"name.first":"xxx"})是不会使用到该索引的。
三、索引数组
MongoDB支持对数组建立索引,这样就可以高效的搜索数组中的特定元素。例如有一个博客文章集合,其中每个文档都表示一篇文章。每篇文章都有一个comments字段,这是一个数组,用来保存别人对这篇文章的评论信息。blog集合结构如下:
db.blog.insert({ "_id":"B001", "title":"MongoDB查询", "comments":[ {"name":"ickes","score":3,"comment":"nice"}, {"name":"xl","score":4,"comment":"nice"}, {"name":"eksliang","score":5,"comment":"nice"}, {"name":"ickes","score":6,"comment":"nice"} ] })
如果要找出comments.score大于5的所有文章,可以在comments.score键上面建立索引:
> db.blog.ensureIndex({"comments.score":1})
对数组建立索引需要注意
- 对数组建立索引,实际上是对数组的每一个元素建立一个索引条目,如果一篇文章有20个评论,那么它就拥有20个索引条目。因此索引的代价比较单值索引的代价高。
- 在数组上建立的索引并不包含任何位置信息:无法使用数组索引查找特定位置的数组元素,比如"comments.4".
- 一个索引中数组字段最多只能有一个。这是为了避免在复合索引中索引条目爆炸性增长。
- 对于某个索引的键,如果这个键在某个文档中是一个数组,那么这个索引就会标记为多键索引。可以从explain()的输出信息中看到一个索引是否为多键索引。如果是多键索引,那么"isMultikey"字段的值就会为true。索引只要被标记为多键索引,就无法再变成非多键索引,即使索引的键从文档中删除也不行。唯一的办法就是删除重建。
四、explain()和hint()
explian()能够提供大量与查询相关的信息。对于速度比较慢的查询来说,这是最重要的诊断工具。通过查看explian()的输出信息,可以知道查询使用了那个索引,以及如果使用他的。对于任意查询来,都可以在最后添加一个explain()调用,但是调用explain()的时间必须是最后。
参考实例:
> db.users.find({"age":{"$gt":10}}).sort({"age":1}).limit(100).explain() { "cursor" : "BtreeCursor age_1_name_1", "isMultiKey" : false, "n" : 100, "nscannedObjects" : 100, "nscanned" : 100, "nscannedObjectsAllPlans" : 100, "nscannedAllPlans" : 100, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 0, "nChunkSkips" : 0, "millis" : 0, "indexBounds" : { "age" : [ [ 10, Infinity ] ], "name" : [ [ { "$minElement" : 1 }, { "$maxElement" : 1 } ] ] }, "server" : "localhost.localdomain:27017", "filterSet" : false }
explain()输出各个信息的含义如下表所示
"cursor" : "BtreeCursor age_1_name_1" | 表示本次查询使用了索引,具体使用了age_1_name_1这个索引 |
"isMultiKey" : false | 用于说明本次查询是否使用了多键索引 |
"n" : 100 | 本次查询返回的文档数量 |
"nscannedObjects" : 100 | 这是MongoDB使用索引指针去磁盘上查找文档的实际次数 |
"nscanned" : 100 | 如果有使用索引,那么这个数字就是检查过的索引个数,如果本次查询是全表扫描,那么这个数字就是检查过的文档个数 |
"scanAndOrder" : false | MongoDB是否在内存中对结果集进行了排序 |
"indexOnly" : false | MongoDB是否只使用索引就可以完成本次查询("覆盖索引") |
"nYields" : 0 | 为了让写入请求能够顺利执行,本次查询暂停的次数。如果有写入请求需要处理,查询会周期性地释放他的锁,以便写人能够顺利执行。然而,在本次查询中没有写入请求,因为查询没有暂停过。 |
"millis" : 0 | 数据库执行本次查询所耗费的毫秒数。这个数字越小,说明查询效率越高 |
indexBounds:{...} | 这个字段描述了索引的使用情况,给出了索引的遍历范围。因为本次查询只使用了age做为查询条件跟排序条件,没有指定第二个键,因此在name键上没有限制,数据库会把用户名介于负无穷("$minElement" : 1)到正无穷("$maxElement" : 1)之间进行搜索 |
hint()方法用于让MongoDB强制使用某个索引,或者查询使用了索引反而效率更低,这个时候可以使用hint()屏蔽索引让查询走全表扫描。
参考实例:强制本次查询使用{"name":1,"age":1}这个索引
> db.users.find({"age":{"$gt":10}}).sort({"age":1}).hint({"name":1,"age":1}).explain()
参考实例:强制本次查询走全表扫描
> db.users.find({"age":{"$gt":10}}).sort({"age":1}).hint({"$natural":true}).explain()--使用{"$natural":1}--$natural 强制全表扫描
五、MongoDB中低效率的操作符
"$where"和"$exists":这两个操作符,完全不能使用索引。
"$ne":通常来说取反的效率比较低。"$ne"查询可以使用索引,但并不是很有效。因为他必须查看所有的索引条目,而不是"$ne"指定的条目,这个时候他就不得不扫描整个索引。
"$not":有时候能够使用索引,但是他通常并不知道要如何使用索引。所以大多数情况"$not"会退化为全表扫描。
"$nin":这个操作符总是会全表扫描
六、OR查询
MongoDB在一次查询中只能使用一个索引(至少我现在用的2.6是这样的),如果你在{"x":1}上有一个索引,在{"y":1}上也有一个索引,在{"x":1,"y":1}上执行查询时,MongoDB只会使用其中一个索引,而不是两个一起使用。"$or"是一个例外,"$or"可以对每个字句都使用索引,因为"$or"实际上是执行两次查询然后将结果合并。
通常来说,使用or查询多次在合并结果,不如单次查询的效率高,对于单个字段,应该尽可能使用$in。
七、MongoDB的查询优化器
MongoDB的查询优化器与其他数据库的稍微不同。基本来说,如果一个索引能够精确匹配一个查询,那么查询优化器就会使用这个索引,如果不能精确匹配,可能会有几个索引都适合你的查询。那MongoDB是怎样选择的呢?答:MongoDB的查询计划会将多个索引并行的去执行,最早返回100个结果的就是胜者,其他查询计划都会被终止。
这个查询计划会被缓冲,接下来的这个查询都会使用他,下面几种情况会重新计划;
- 最初的计划评估之后集合发生了比较大的数据波动,查询优化器就会重新挑选可行的查询计划。
- 建立索引时。
- 每执行1000次查询之后,查询优化器就会重新评估查询计划
八、何时不应该使用索引
提取较小的子数据集时,索引非常有效(所以才有了分页)。也有一些查询不使用索引会更快。结果集在原集合中所占的比例越大,查询效率越慢。因为使用索引需要进行两次查找:一次查找索引条目,一次根据索引指针去查找相应的文档。而全表扫描只需要进行一次查询。在最坏的情况,使用索引进行查找次数会是全表扫描的两倍。效率会明显比全表扫描低。
可惜并没有一个严格的规则可以告诉我们,如果根据索引大小、文档大小来判断什么时候索引很有用,一般来说,如果查询需要返回集合内30%的文档(或者更多),那就应该测试全表扫描和走索引查询那个速度比较快。这个数字也会在2%~60%之间进行波动。
这个时候可以使用hint({"$natural":true})强制查询走全表扫描。
相关推荐
2. 数据库与集合:介绍MongoDB中的数据库概念,如何创建和切换数据库,以及集合(类似于关系数据库中的表)的创建和操作。 3. 文档与插入:深入讲解文档的结构和组成,以及如何向集合中插入单个或多个文档。 4. ...
2. **数据存储**:详细解释MongoDB的数据存储机制,包括BSON(二进制JSON)格式,以及如何设计合适的文档结构以优化查询性能。 3. **查询语言**:深入解析MongoDB的查询语法,包括查询操作符、投影、排序、分页,...
本篇文章将深入探讨MongoDB的核心概念、功能以及如何利用这两本书籍——《深入学习MongoDB》和《MongoDB权威指南(第2版)》来提升你的MongoDB技能。 首先,MongoDB的基础知识包括它的NoSQL数据模型。不同于传统的...
在学习MongoDB时,你需要掌握基本的CRUD操作、数据模型设计、索引使用、复制集的建立和维护、分片集群的搭建以及性能调优策略等。理解NoSQL数据库的核心理念,如灵活性、可伸缩性和高性能,将有助于你更好地应用...
- **监控与调优**:为了确保MongoDB的稳定运行,需要对其性能进行持续监控并根据需要进行调优。 - **备份与恢复**:制定合理的备份策略并在必要时进行数据恢复是MongoDB运维工作的重要组成部分。 综上所述,《最新...
最后,"大数据存储——MongoDB实战指南(迷你书)"可能会专注于MongoDB在大数据场景下的应用。这本书可能会讨论如何利用MongoDB处理大规模数据的挑战,如数据导入导出、性能调优、数据安全和合规性。它可能还会介绍...
3. MongoDB高级特性:如索引创建、聚合框架、地理空间索引等。 4. PHP Redis扩展的使用:安装、配置和基本操作命令的介绍。 5. Redis数据类型的应用:如何根据业务需求选择合适的数据类型,并进行操作。 6. Redis...
5. **数据库技术**:可能采用了MySQL、MongoDB等数据库存储索引数据和用户信息,同时可能涉及SQL优化和NoSQL数据结构的选择。 6. **用户体验设计**:积分系统的存在,可能涉及到用户界面(UI)和用户体验(UX)设计...
- **索引优化**:创建合适的数据索引,提高查询速度。 6. **Web数据库安全**: - **权限管理**:设置不同级别的用户权限,防止未授权访问。 - **加密存储**:敏感数据应加密存储,保护用户隐私。 - **SQL注入...
1. **数据库模型与设计**:在设计任何数据库之前,首先需要选择合适的数据库模型,如关系型数据库(如MySQL、Oracle)、非关系型数据库(如MongoDB、Cassandra)等。在这个网购平台中,关系型数据库可能更为适用,...
- 数据模型:理解并掌握三种主要的数据模型——关系型模型(如SQL)、层次模型和网络模型。 - 数据结构:了解B树、B+树、哈希表等数据结构及其在数据库中的应用。 - ACID特性:原子性(Atomicity)、一致性...
10. **数据库性能调优**:了解如何监控数据库性能,使用查询分析器找出性能瓶颈,并应用优化策略,如调整表分区、使用存储过程、合理设计索引等。 陕西师范大学的数据库考试可能会涵盖以上知识点的综合应用,考生需...
2. 数据模型:课程会深入讲解三种主要的数据模型——层次模型、网状模型和关系模型。其中,关系模型是最常见的,基于E-R(实体-关系)模型,使用表格来表示数据。 3. SQL语言:SQL(结构化查询语言)是用于管理和...
同时,学习索引优化、查询优化和数据库性能调优策略。 4. **数据库安全与备份恢复**:掌握用户权限管理,数据库的备份策略(如完整备份、增量备份和差异备份),以及数据恢复技术,如日志恢复和前滚/后滚操作。 5....
2. **Sina App Engine架构——云计算时代的分布式Web服务解决方案.mht**:Sina App Engine可能是新浪公司提供的一个云计算平台,用于构建和运行分布式Web服务。这个文件可能探讨了如何在云环境中使用分布式数据库来...
9. **性能优化**:数据库性能优化包括索引设计、查询优化、分区、缓存和数据库调优。索引可以加速查询,查询优化器选择最优执行计划,分区将大表分成小块,缓存提高数据访问速度,调优涉及参数调整和架构改进。 10....
2. **数据库设计**:理解数据库的概念模型,例如实体关系模型(ER模型),以及如何通过创建表来实现这些模型。了解主键、外键、唯一性约束和索引等数据库设计原则。 3. **SQL查询优化**:如何编写高效的SQL查询,...
此外,事务处理、索引优化、查询性能调优也是必备技能。 5. **Web开发与框架**:深入理解HTTP协议,熟悉Servlet和JSP技术,掌握Spring Boot、Spring Cloud等主流Java Web框架。同时,需要了解MVC设计模式,以及...
2. 数据库设计:包括概念设计(ER模型)、逻辑设计(表结构设计)和物理设计(索引、分区等)。良好的数据库设计能够提高查询效率,减少数据冗余,保证数据的一致性。 3. 数据库优化:涉及索引策略、查询优化、存储...