1、準備
php
須要在mongodb中添加測試數據java
db.user.insert({"name":"張三","age":34,"job":"java 開發","phone":"18989834028","addr":"廣東深圳福田"}) db.user.insert({"name":"李四","age":29,"job":"php 開發","phone":"18984834098","addr":"廣東深圳南山"}) db.user.insert({"name":"王五","age":38,"job":"部門經理","phone":"18981834098","addr":"廣東深圳羅湖"}) db.user.insert({"name":"趙一","age":31,"job":"產品經理","phone":"18989764098","addr":"廣東廣州"}) db.user.insert({"name":"錢二","age":26,"job":"銷售","phone":"18989834968","addr":"廣東珠海"}) db.user.insert({"name":"週六","age":54,"job":"銷售經理","phone":"18981234098","addr":"廣東中山"}) db.user.insert({"name":"吳奇","age":17,"job":"學生","phone":"18735834098","addr":"廣東韶關"}) db.user.insert({"name":"鄭八","age":45,"job":"教師","phone":"18989834098","addr":"廣東惠州"}) db.user.insert({"name":"馮峯","age":23,"job":"java 開發","phone":"13689834098","addr":"廣東廣州越秀"})
咱們知道使用mongodb objectId數據主鍵_id是默認有索引的。下面先按名稱和手機建立單獨的索引,而後建立一個聯合主鍵mongodb
db.user.ensureIndex({"phone":1}); db.user.ensureIndex({"name":1}); db.user.ensureIndex({"name":1,"phone":1});
查看下如今已有的索引測試
>db.user.getIndexes(); [ { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.user" }, { "v" : 1, "key" : { "name" : 1 }, "name" : "name_1", "ns" : "test.user" }, { "v" : 1, "key" : { "phone" : 1 }, "name" : "phone_1", "ns" : "test.user" }, { "v" : 1, "key" : { "name" : 1, "phone" : 1 }, "name" : "name_1_phone_1", "ns" : "test.user" } ]
2、測試spa
使用explain()方法查看執行計劃,首先看下不使用查詢條件。code
> db.user.find().explain(); { "queryPlanner" : { "winningPlan" : { "stage" : "COLLSCAN", }
能夠看到沒有使用查詢條件的狀況下使用的是全表掃描。索引
再來看下根據name,和phone做爲查詢條件的狀況下,使用的是聯合索引,仍是單獨的索引。開發
> db.user.find({"phone":"13678763456","name":"李斯"}).explain(); { "queryPlanner" : { "winningPlan" : { "indexName" : "name_1", }, "rejectedPlans" : [ { "indexName" : "name_1_phone_1", .... } }, { ..... "indexName" : "phone_1", ...... } } ] }, }
能夠看到,並無使用聯合主鍵並無在最優計劃(winningPlan)中,而是在rejectedplan中。先使用了phone的單獨索引。調整查詢條件順序,索引的順序是name,phone,看下get
> db.user.find({"name":"李斯","phone":"18737260965"}).explain(); { "queryPlanner" : { .... "winningPlan" : { ...... "inputStage" : { ....... "indexName" : "name_1", ...... } }, "rejectedPlans" : [ { "inputStage" : { ......... "indexName" : "name_1_phone_1", ........ }, { "inputStage" : { "indexName" : "phone_1", ....... } ] }, }
調整順序以後仍是同樣,在winningPlan使用name的單獨索引而不是聯合索引。刪除單獨的索引再測試input
db.user.dropIndex("name_1"); db.user.dropIndex("phone_1");
測試
> db.user.find({"name":"李斯","phone":"18737260965"}).explain(); .... "winningPlan" : { ... "indexName" : "name_1_phone_1", ... > db.user.find({"phone":"13678763456","name":"李斯"}).explain(); "winningPlan" : { ..... "indexName" : "name_1_phone_1", .... > db.user.find({"phone":"13678763456","name":"李斯","age":23}).explain(); "winningPlan" : { 。。。 "indexName" : "name_1_phone_1", > db.user.find({"phone":"13678763456","age":23,"name":"李斯"}).explain(); "winningPlan" : { "indexName" : "name_1_phone_1", > db.user.find({"phone":"13678763456"}).explain(); "winningPlan" : { "stage" : "COLLSCAN", > db.user.find({"name":"張三"}).explain(); "winningPlan" : { 。。。。 "indexName" : "name_1_phone_1", > db.user.find({"age":33,"name":"張三"}).explain(); "winningPlan" : { 。。。。 "indexName" : "name_1_phone_1",
能夠看到對於聯合索引,若是隻使用一部分,則必須是按順序的(在本測試中只用使用name纔用到索引),若是知足條件(name,phone 都出如今條件中),則沒有順序要求。
3、終結
經過簡單的測試,對mongodb( "version" : "3.2.4",)的索引工做原理理解:
一、若是某個字段同時出如今單獨索引和聯合索引中,winningPlan 使用的是單獨索引。
二、若是查詢條件知足索引的條件,則不須要管理條件字段順序,
三、若是查詢條件字段不知足聯合索引,則必須是按建立索引的字段順序查詢纔會使用索引。(能夠有其餘字段在索引字段前如,{"age":33,"name":"張三"}).