wangming1993 / issues

记录学习中的一些问题,体会与心得 https://wangming1993.github.io/issues
8 stars 4 forks source link

MongoDB 索引小结 #19

Open wangming1993 opened 8 years ago

wangming1993 commented 8 years ago

MongoDB Indexes

{ "item": 1, "location": 1, "stock": 1 }

支持:

{ item: 1 }
{ item: 1, location: 1 }
db.events.createIndex( { "username" : 1, "date" : -1 } )

支持sort:

db.events.find().sort( { username: -1, date: 1 } )
db.events.find().sort( { username: 1, date: -1 } )

不支持:

db.events.find().sort( { username: 1, date: 1 } )

实验

MongoDB 版本

~ » mongo --version                                     
MongoDB shell version: 3.0.8

单个索引

创建订单表, 插入10000条数据

~ » mongo
for(var i = 0; i < 10000; i++) { 
    db.order.insert({"sku": i+1, "cid": 10000 - i});
}

根据_sku_查询, 使用_explain()_进行分析

 db.order.find({"sku":100}).explain()
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.order",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "sku" : {
                "$eq" : 100
            }
        },
        "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "sku" : {
                    "$eq" : 100
                }
            },
            "direction" : "forward"
        },
        "rejectedPlans" : [ ]
    },
    "ok" : 1
}

观察到 winningPlanstage_COLLSCAN_ 为 _全表扫描_

添加索引

db.order.ensureIndex({"sku":1})

再次根据_sku_查询

> db.order.find({"sku":100}).explain()
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.order",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "sku" : {
                "$eq" : 100
            }
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "sku" : 1
                },
                "indexName" : "sku_1",
                "isMultiKey" : false,
                "direction" : "forward",
                "indexBounds" : {
                    "sku" : [
                        "[100.0, 100.0]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ ]
    }
}

发现现在 stage_IXSCAN_, 意为 index scan, 索引扫描, 此时利用了索引

复合索引

创建collection, 添加数据

for(var i = 0; i < 10000; i++) { 
    db.order_2.insert({"sku":i+1, "cid":9999-i});
}

添加复合索引 _sku_1_cid1

db.order_2.ensureIndex({"sku":1, "cid":1});

观察现象

查询条件 查找方式 是否使用索引
sku : 100 IXSCAN
cid : 100 COLLSCAN
sku:2, cid:9998 IXSCAN
cid:2, sku:9998 IXSCAN

4个字段组成的复合索引支持的查询类型

for(var i = 0; i < 10000; i++) { 
    db.order_4.insert({"sku":i+1, "cid":9999-i, "status": i * 100, "order" : i});
}
db.order_4.ensureIndex({"sku":1,"cid":1,"status":1,"order":1})
索引 sku_1_cid_1_status_1_order_1
查询条件 查找方式 是否使用索引
sku : 100 IXSCAN
cid : 100 IXSCAN
status : 100 IXSCAN
order : 100 IXSCAN
sku:2, cid:9998 IXSCAN
sku:9998, status: 100 IXSCAN
sku:9998, order: 100 IXSCAN
cid:1, status:100 COLLSCAN
cid:1, order: 0 COLLSCAN
status:100, order:1 COLLSCAN
sku:1,cid:100,status:1 IXSCAN
sku:1,cid:100,order:1 IXSCAN
sku:1,status:100,order:0 IXSCAN
cid:1,status:100,order:0 COLLSCAN
sku:1,cid:100,status:1,order:1 IXSCAN

综上所述: