`

mongodb 使用索引优化查询

阅读更多

数据库 > tmp

集合 > app_down

 

> use tmp

switched to db tmp

R:使用tmp数据库

 

> db.createCollection("app_down");

{ "ok" : 1 }

R:创建集合

 

> db.app_down.save({"app_id":1002,"count_down":33,"stat_date":"2014-01-01"});

> db.app_down.save({"app_id":1102,"count_down":33,"stat_date":"2014-01-02"});

> db.app_down.save({"app_id":1100,"count_down":33,"stat_date":"2014-01-02"});

R:模拟测试数据

 

> db.app_down.find();

{ "_id" : ObjectId("534f72c0c7f347b9e5b44efc"), "app_id" : 1002, "count_down" : 33, "stat_date" : "2014-01-01" }

{ "_id" : ObjectId("534f72cac7f347b9e5b44efd"), "app_id" : 1102, "count_down" : 33, "stat_date" : "2014-01-02" }

{ "_id" : ObjectId("534f72cec7f347b9e5b44efe"), "app_id" : 1100, "count_down" : 33, "stat_date" : "2014-01-02" }

R:查询所有数据

 

> db.app_down.getIndexes();

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"ns" : "tmp.app_down",

"name" : "_id_"

}

]

R: 查询集合索引列表,插入数据时默认会给_id创建"升序"索引,在find()中不排序情况下默认是按照_id"升序" 排序

 

> db.app_down.find({app_id:1100}).explain();

{

"cursor" : "BasicCursor",

"isMultiKey" : false,

"n" : 1,

"nscannedObjects" : 3,

"nscanned" : 3,

"nscannedObjectsAllPlans" : 3,

"nscannedAllPlans" : 3,

"scanAndOrder" : false,

"indexOnly" : false,

"nYields" : 0,

"nChunkSkips" : 0,

"millis" : 0,

"indexBounds" : {

 

},

"server" : "tts-0001:27017"

}

R:查询分析 cursor索引类型,BasicCursor没有使用索引,

 

> db.app_down.ensureIndex({app_id:1});

R:给字段app_id创建升序索引

 

> db.app_down.getIndexes();

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"ns" : "tmp.app_down",

"name" : "_id_"

},

{

"v" : 1,

"key" : {

"app_id" : 1

},

"ns" : "tmp.app_down",

"name" : "app_id_1"

}

]

R:索引名字以字段+升序/降序组成,_id_默认升序,app_id_1指按照app_id升序

 

> db.app_down.find({app_id:1100}).explain();

{

"cursor" : "BtreeCursor app_id_1",

"isMultiKey" : false,

"n" : 1,

"nscannedObjects" : 1,

"nscanned" : 1,

"nscannedObjectsAllPlans" : 1,

"nscannedAllPlans" : 1,

"scanAndOrder" : false,

"indexOnly" : false,

"nYields" : 0,

"nChunkSkips" : 0,

"millis" : 0,

"indexBounds" : {

"app_id" : [

[

1100,

1100

]

]

},

"server" : "tts-0001:27017"

}

R:创建索引后在执行查询分析,明显看到提速

 

> db.app_down.save({"app_id":1002,"count_down":33,"stat_date":"2014-01-01"});

R:继续插入测试数据

 

> db.app_down.find();

{ "_id" : ObjectId("534f72c0c7f347b9e5b44efc"), "app_id" : 1002, "count_down" : 33, "stat_date" : "2014-01-01" }

{ "_id" : ObjectId("534f72cac7f347b9e5b44efd"), "app_id" : 1102, "count_down" : 33, "stat_date" : "2014-01-02" }

{ "_id" : ObjectId("534f72cec7f347b9e5b44efe"), "app_id" : 1100, "count_down" : 33, "stat_date" : "2014-01-02" }

{ "_id" : ObjectId("534f7383c7f347b9e5b44f00"), "app_id" : 1002, "count_down" : 33, "stat_date" : "2014-01-01" }

R:可以看到刚刚插入的数据

 

> db.app_down.ensureIndex({app_id:1,stat_date:1},{unique:true});

Thu Apr 17 14:26:23.559 JavaScript execution failed: ReferenceError: date is not defined

R:按照业务逻辑app_id和stat_date必须是唯一的,此时创建唯一索引,而原始数据并不唯一,此时创建索引失败

 

> db.app_down.ensureIndex({app_id:1,stat_date:1},{unique:true,dropDups:true});

R:创建唯一索引,同时删除重复的记录,遵循先近后出,后创建的会被先删除

 

> db.app_down.find();

{ "_id" : ObjectId("534f72c0c7f347b9e5b44efc"), "app_id" : 1002, "count_down" : 33, "stat_date" : "2014-01-01" }

{ "_id" : ObjectId("534f72cac7f347b9e5b44efd"), "app_id" : 1102, "count_down" : 33, "stat_date" : "2014-01-02" }

{ "_id" : ObjectId("534f72cec7f347b9e5b44efe"), "app_id" : 1100, "count_down" : 33, "stat_date" : "2014-01-02" }

R:看到最后添加的一条重复数据在创建唯一索引时被删掉了

 

> db.app_down.save({"app_id":1002,"count_down":33,"stat_date":"2014-01-01"});

E11000 duplicate key error index: tmp.app_down.$app_id_1_stat_date_1  dup key: { : 1002.0, : "2014-01-01" }

R:在创建唯一索引的集合上继续添加重复数据,无法添加成功

 

> db.app_down.save({"app_id":1112,"count_down":33,"stat_date":"2014-01-01"});

R:继续插入测试数据(不违反唯一索引约束)

 

> db.app_down.find();

{ "_id" : ObjectId("534f72c0c7f347b9e5b44efc"), "app_id" : 1002, "count_down" : 33, "stat_date" : "2014-01-01" }

{ "_id" : ObjectId("534f72cac7f347b9e5b44efd"), "app_id" : 1102, "count_down" : 33, "stat_date" : "2014-01-02" }

{ "_id" : ObjectId("534f72cec7f347b9e5b44efe"), "app_id" : 1100, "count_down" : 33, "stat_date" : "2014-01-02" }

{ "_id" : ObjectId("534f74fbc7f347b9e5b44f09"), "app_id" : 1112, "count_down" : 33, "stat_date" : "2014-01-01" }

R:可以看到刚刚插入的数据

 

> db.app_down.save({"app_id":1112,"count_down":33});

R:继续插入测试数据

 

> db.app_down.find();

{ "_id" : ObjectId("534f72c0c7f347b9e5b44efc"), "app_id" : 1002, "count_down" : 33, "stat_date" : "2014-01-01" }

{ "_id" : ObjectId("534f72cac7f347b9e5b44efd"), "app_id" : 1102, "count_down" : 33, "stat_date" : "2014-01-02" }

{ "_id" : ObjectId("534f72cec7f347b9e5b44efe"), "app_id" : 1100, "count_down" : 33, "stat_date" : "2014-01-02" }

{ "_id" : ObjectId("534f74fbc7f347b9e5b44f09"), "app_id" : 1112, "count_down" : 33, "stat_date" : "2014-01-01" }

{ "_id" : ObjectId("534f751bc7f347b9e5b44f0a"), "app_id" : 1112, "count_down" : 33 }

R:可以看到刚刚插入的数据

 

> db.app_down.getIndexes();

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"ns" : "tmp.app_down",

"name" : "_id_"

},

{

"v" : 1,

"key" : {

"app_id" : 1

},

"ns" : "tmp.app_down",

"name" : "app_id_1"

},

{

"v" : 1,

"key" : {

"app_id" : 1,

"stat_date" : 1

},

"unique" : true,

"ns" : "tmp.app_down",

"name" : "app_id_1_stat_date_1",

"dropDups" : true

}

]

R:查询现在的索引列表

 

> db.app_down.ensureIndex({app_id:1,stat_date:1},{unique:true});

R:创建重复索引(重复只包含字段,ensureIndex函数的第一个参数)

 

> db.app_down.getIndexes();

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"ns" : "tmp.app_down",

"name" : "_id_"

},

{

"v" : 1,

"key" : {

"app_id" : 1

},

"ns" : "tmp.app_down",

"name" : "app_id_1"

},

{

"v" : 1,

"key" : {

"app_id" : 1,

"stat_date" : 1

},

"unique" : true,

"ns" : "tmp.app_down",

"name" : "app_id_1_stat_date_1",

"dropDups" : true

}

]

R:查询集合的索引列表

 

> db.app_down.dropIndex("app_id_1_stat_date_1");

{ "nIndexesWas" : 3, "ok" : 1 }

R:删除索引

 

> db.app_down.getIndexes();

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"ns" : "tmp.app_down",

"name" : "_id_"

},

{

"v" : 1,

"key" : {

"app_id" : 1

},

"ns" : "tmp.app_down",

"name" : "app_id_1"

}

]

R:查询集合的索引列表

 

> db.app_down.ensureIndex({app_id:1,stat_date:1},{unique:true,dropDups:true,sparse:true});

R:sparse参数指稀疏索引,索引字段值为空时不参与索引检索,为节省空间,这些记录不参与到索引中

 

> db.app_down.getIndexes();

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"ns" : "tmp.app_down",

"name" : "_id_"

},

{

"v" : 1,

"key" : {

"app_id" : 1

},

"ns" : "tmp.app_down",

"name" : "app_id_1"

},

{

"v" : 1,

"key" : {

"app_id" : 1,

"stat_date" : 1

},

"unique" : true,

"ns" : "tmp.app_down",

"name" : "app_id_1_stat_date_1",

"dropDups" : true,

"sparse" : true

}

]

R:可以看到使用了松散索引

 

> db.app_down.ensureIndex({app_id:1,stat_date:-1},{unique:true,dropDups:true,sparse:true,background:true});

R:在给大数据创建索引时防止锁表发生,使用后台索引

 

> db.app_down.getIndexes();

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"ns" : "tmp.app_down",

"name" : "_id_"

},

{

"v" : 1,

"key" : {

"app_id" : 1

},

"ns" : "tmp.app_down",

"name" : "app_id_1"

},

{

"v" : 1,

"key" : {

"app_id" : 1,

"stat_date" : 1

},

"unique" : true,

"ns" : "tmp.app_down",

"name" : "app_id_1_stat_date_1",

"dropDups" : true,

"sparse" : true

},

{

"v" : 1,

"key" : {

"app_id" : 1,

"stat_date" : -1

},

"unique" : true,

"ns" : "tmp.app_down",

"name" : "app_id_1_stat_date_-1",

"dropDups" : true,

"sparse" : true,

"background" : true

}

]

R:可以看到后台索引创建了,注意此时的索引字段排序不同上一个索引

 

> db.app_down.find({app_id:1002,stat_date:"2014-01-01"}).sort({count_down:1}).explain();

{

"cursor" : "BtreeCursor app_id_1",

"isMultiKey" : false,

"n" : 1,

"nscannedObjects" : 1,

"nscanned" : 1,

"nscannedObjectsAllPlans" : 2,

"nscannedAllPlans" : 4,

"scanAndOrder" : true,

"indexOnly" : false,

"nYields" : 0,

"nChunkSkips" : 0,

"millis" : 0,

"indexBounds" : {

"app_id" : [

[

1002,

1002

]

]

},

"server" : "tts-0001:27017"

}

R:看到 "scanAndOrder" : true 意味着悲剧发生了,这次查询是先进行了scan获取到数据,再进行了独立的排序操作的,如有必要把排序字段也加到索引中吧

 

> db.app_down.find({stat_date:"2014-01-01"}).explain();

{

"cursor" : "BasicCursor",

"isMultiKey" : false,

"n" : 2,

"nscannedObjects" : 5,

"nscanned" : 5,

"nscannedObjectsAllPlans" : 5,

"nscannedAllPlans" : 5,

"scanAndOrder" : false,

"indexOnly" : false,

"nYields" : 0,

"nChunkSkips" : 0,

"millis" : 0,

"indexBounds" : {

 

},

"server" : "tts-0001:27017"

}

> db.app_down.find({stat_date:"2014-01-01",app_id:1002}).explain();

{

"cursor" : "BtreeCursor app_id_1_stat_date_1",

"isMultiKey" : false,

"n" : 1,

"nscannedObjects" : 1,

"nscanned" : 1,

"nscannedObjectsAllPlans" : 1,

"nscannedAllPlans" : 1,

"scanAndOrder" : false,

"indexOnly" : false,

"nYields" : 0,

"nChunkSkips" : 0,

"millis" : 0,

"indexBounds" : {

"app_id" : [

[

1002,

1002

]

],

"stat_date" : [

[

"2014-01-01",

"2014-01-01"

]

]

},

"server" : "tts-0001:27017"

}

> db.app_down.dropIndex("app_id_1");

{ "nIndexesWas" : 4, "ok" : 1 }

 

> db.app_down.find({app_id:1002}).explain();

{

"cursor" : "BtreeCursor app_id_1_stat_date_1",

"isMultiKey" : false,

"n" : 1,

"nscannedObjects" : 1,

"nscanned" : 1,

"nscannedObjectsAllPlans" : 1,

"nscannedAllPlans" : 1,

"scanAndOrder" : false,

"indexOnly" : false,

"nYields" : 0,

"nChunkSkips" : 0,

"millis" : 0,

"indexBounds" : {

"app_id" : [

[

1002,

1002

]

],

"stat_date" : [

[

{

"$minElement" : 1

},

{

"$maxElement" : 1

}

]

]

},

"server" : "tts-0001:27017"

}

 

R:如果想用到复合索引,必须在查询条件中包含复合索引中的前N个索引列。然而如果查询条件中的键值顺序和复合索引中的创建顺序不一致的话,MongoDB可以智能的帮助我们调整该顺序,以便使复合索引可以为查询所用

 

 

 

 

 

关于explain函数返回字段的解释:

 

1 "cursor":如果没有使用索引,游标的类型是BasicCursor,查询使用了索引,MongoDB中索引存储在B树结构中,BtreeCursor类型的游标。

 

2 "nscanned"/"nscannedObjects":表明当前这次查询一共扫描了集合中多少个文档,让这个数值和返回文档的数量越接近越好

 

3 "n":当前查询返回的文档数量

 

4 "millis":当前查询所需时间,毫秒数

 

 

5 "indexBounds":当前查询具体使用的索引

分享到:
评论

相关推荐

    MONGODB的索引探究

    MongoDB的索引是数据库性能优化的关键因素,与MySQL、Oracle等关系型数据库中的索引原理相似,但具有自身的特性和限制。MongoDB的索引建立在Collection(表)级别,采用B-树数据结构来加速查询和排序操作。 1. 默认...

    MongoDB索引与查询.pdf

    3. **hint操作**:`hint()` 方法用于强制 MongoDB 使用特定的索引来执行查询,这在需要优化查询性能时特别有用。例如,当系统选择的默认索引不是最有效时,可以使用 `hint()` 指定最佳索引。 4. **索引的存储和性能...

    MongoDB覆盖索引查询.pdf

    MongoDB 覆盖索引查询是一种优化查询性能的技术,尤其适用于需要高效检索和返回大量数据的场景。在MongoDB中,覆盖索引查询是指查询涉及的所有字段都包含在创建的索引中,这样MongoDB就无需回表(即不需访问原始文档...

    MongoDB查询性能验证及优化

    MongoDB使用查询解释器来解析和执行查询操作。通过`explain()`方法,我们可以获取查询的执行计划,包括扫描的文档数量、使用的索引、是否进行了排序等关键信息。例如,以下Java代码片段展示了如何在`MainTest.java`...

    Mongodb索引的优化

    MongoDB 的索引优化是一项关键任务,涉及索引的选择、创建、监控和维护。理解索引的工作原理以及如何有效地利用它们,是确保MongoDB应用高效运行的关键。通过持续的监控和优化,可以显著提高查询性能,减少不必要的...

    30分钟学MongoDB系列——性能优化和性能监控篇

    例如,如果发现查询操作没有使用索引,系统会进行全表扫描,这时添加索引会大幅提升查询效率。优化前后的对比可以直观显示出性能的提升。 3. 慢查询日志:慢查询日志是数据库性能优化的利器。MongoDB中的慢查询记录...

    mongodb优化

    针对 MongoDB 的优化是提高数据库性能的关键,这通常涉及到多个方面,包括内存配置、查询优化、索引管理和集群架构调整等。 首先,我们可以修改 MongoDB 的默认内存配置以适应更大的数据处理需求。在 MongoDB ...

    基于MongoDB数据库索引构建情况全面分析

    当我们对一个查询使用`explain()`,MongoDB会返回查询计划,包括使用的索引、扫描的文档数、是否存在全表扫描以及查询的执行时间等。这有助于识别是否需要创建或优化索引,以提高查询效率。 综上所述,全面分析...

    MongoDB学习笔记(六) MongoDB索引用法和效率分析

    在MongoDB中,索引对于优化查询性能至关重要,尤其在处理大量数据时。下面将详细介绍MongoDB中不同类型的索引创建、查询及维护。 首先,MongoDB有一个默认的`_id`字段,它扮演着主键的角色。每个集合在创建时都会...

    MongoDB 覆盖索引查询

    MongoDB的覆盖索引查询是一种优化查询性能的技术,它的核心在于通过索引来满足查询的全部需求,从而避免了对整个文档的访问。这种查询方法在处理大数据量时尤其有用,因为它减少了磁盘I/O操作,提高了查询速度。下面...

    mongodb如何建立索引

    1. MongoDB 索引和 MySQL 索引非常相似,并且对于 MySQL 的索引优化有很多也适用于 MongoDB。 2. 索引策略需要基于很多的重要因素,包含了你期望查询的类型,数据读取与写入的比率,甚至于你服务器的空闲内存。 3....

    NoSQL数据库(如MongoDB,Cassandra):MongoDB的索引与性能优化.docx

    NoSQL数据库(如MongoDB,Cassandra):MongoDB的索引与性能优化.docx

    MongoDB简单索引.pdf

    合理使用索引可以大幅提升查询效率,同时,理解并熟练运用各种索引参数可以进一步定制索引行为,满足特定的业务需求。在设计和管理MongoDB数据库时,应根据查询模式和数据特性,明智地创建和维护索引,以实现最佳的...

    MongoDB 索引 和explain分析查询速度1

    需要注意的是,当查询条件中包含复合索引的前N个字段时,MongoDB才会使用该索引。此外,查询条件中的字段顺序与索引创建顺序不一致时,MongoDB会自动调整以匹配索引。 二、唯一索引 默认创建的索引是非唯一的,若...

    MongoDB高级索引.pdf

    本文将深入探讨如何在 MongoDB 中为数组字段和子文档字段创建高级索引,以优化查询性能。 首先,让我们了解一下在数组字段上创建索引的方法。在上述示例中,`tags` 字段是一个数组,包含字符串如 "music", "cricket...

    MongoDB索引限制.pdf

    - **内存使用**:MongoDB 的索引主要存储在内存中,以提高查询速度。因此,你需要确保索引的大小不超过服务器的可用 RAM。如果索引超出内存限制,MongoDB 将开始使用磁盘上的缓存,这可能导致性能下降。 2. **查询...

    1亿条记录的MongoDB数据库随机查询性能测试

    2. **索引优化**:合理设计索引,针对频繁查询的字段创建索引,以提高查询效率。 3. **硬件配置**:使用高性能的处理器和高速磁盘,如SSD,以提升I/O性能。 4. **分片和复制集**:对于非常大的数据集,可以考虑使用...

    mongodb性能优化.pptx

    这可能包括调整配置、优化查询语句、添加索引等。 #### 二、MongoDB自监控工具 MongoDB提供了多种内置工具帮助用户监控数据库的状态,这些工具对于性能调优至关重要。下面详细介绍几种常用的监控工具。 ##### 1. ...

Global site tag (gtag.js) - Google Analytics