mongodb06---索引

Posted 672530440

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mongodb06---索引相关的知识,希望对你有一定的参考价值。

索引(就像书的目录,先找大致的位置再细找,不是从头开始找):

mongodb每行的列可以完全不同,没有列的概念。


索引作用类型:
1:单列索引
2:多列索引
3:子文档索引

索引性质:
0:普通索引
1.唯一索引
2.稀疏索引
3.哈希索引


语法: db.collections.ensureIndex({field:1});
注: 1:默认是增序建索引。  2:默认索引是用btree组织
例: db.goods.ensureIndex({goods_id:1});
解释:1. 按goods_id增序规律建立索引。   2. 用btree组织索引文件

 


索引创建
1:索引提高查询速度,降低写入速度,权衡常用的查询字段,不必在太多列上建索引
2.在mongodb中,索引可以按字段升序/降序来创建,便于排序
3.默认是用btree来组织索引文件,2.4版本以后,也允许建立hash索引.



use shop
db.goods.find(
{
    goods_name:{$regex:/索爱/}
}
).explain():  //查看查询计划

"cursor" : "BasicCursor", ----说明没有索引发挥作用(因为没有索引,插入数据的时候要写入索引文件,所以写入更改速度减慢了),则从头找到尾,mongo默认是btree建的索引,
"nscannedObjects" : 1000 ---理论上要扫描多少行
cursor" : "BtreeCursor sn_1", 用到的btree索引






创建普通的单列索引:db.goods.ensureIndex({field:1/-1});  1是升续 2是降续
db.goods.ensureIndex( {shop_price:-1} )
db.goods.find({shop_price:1328}).explain()


查看当前索引状态: db.collection.getIndexes();
use shop
db.bar.ensureIndex( {title:-1} )
db.bar.getIndexes():
[
    {
        "v" : 2,
        "key" : {
            "_id" : 1          //id索引
        },
        "name" : "_id_",
        "ns" : "shop.bar"
    },
    {
        "v" : 2,
        "key" : {
            "title" : -1.0   //title索引
        },
        "name" : "title_-1",
        "ns" : "shop.bar"
    }
]



use shop
db.goods.getIndexes()
db.goods.find({goods_name:{$regex:/索爱/}}).explain():
{
        "v" : 2,
        "key" : {
            "goods_name" : -1.0
        },
        "name" : "goods_name_-1",
        "ns" : "shop.goods"
}:

"indexName" : "goods_name_-1",
"indexBounds" : {
                    "goods_name" : [ 
                        "[/索爱/, /索爱/]", 
                        "({}, \"\"]"
                    ]
                }

db.collection.dropIndex({filed:1/-1});   //删除索引要指定-1,1类型。
db.collection.dropIndexes();    //全部删除,id索引默认就在,不能删掉,



//多列索引,单列索引只是查询一个列的时候用到,当需要按照多列查询的时候就要用到多列索引。
2列分别加索引是各自不影响,多列索引是把2列当成一个整体看没有区分2列了。

创建多列索引  db.collection.ensureIndex({field1:1/-1, field2:1/-1});
db.goods.ensureIndex({goods_name:1,shop_price:1})    //经常goods_name和shop_price要一起查,比单列索引要快。
db.goods.getIndexes():
[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",         //id索引
        "ns" : "shop.goods"
    },
    {
        "v" : 2,
        "key" : {
            "goods_name" : 1.0,    //多列索引
            "shop_price" : 1.0
        },
        "name" : "goods_name_1_shop_price_1",   //索引的名字
        "ns" : "shop.goods"                //namespace
    }
]
db.goods.find(
{
    goods_name:{$regex:/诺基亚/},
    $and:
    [
        {shop_price:{$gt:100}},
        {shop_price:{$gt:300}}
    ]
 }
).explain():

 "indexName" : "goods_name_1_shop_price_1",
 "indexVersion" : 2,
 "indexBounds" : {
                    "goods_name" : [ 
                        "[\"\", {})", 
                        "[/诺基亚/, /诺基亚/]"
                    ],
                    "shop_price" : [ 
                        "(300.0, inf.0]"
                    ]
                }

                
                
//子文档索引
创建子文档索引
db.collection.ensureIndex({filed.subfield:1/-1});

db.goods.insert({name:nokia,spc:{weight:120,area:taiwan}})
db.goods.insert({name:sanxing,spc:{weight:100,area:hanguo}})
db.goods.find({name:nokia})
//查询area=taiwan的,
db.goods.find({area:taiwan})   //因为没有area属性,area是在spc属性下面,这种有子文档的
db.goods.find({spc.area:taiwan})
db.goods.ensureIndex({spc.area:1})   //子文档就索引
db.goods.getIndexes()
db.goods.find({spc.area:taiwan}).explain():
{
    "v" : 2,
    "key" : {
        "spc.area" : 1.0
    },
    "name" : "spc.area_1",
    "ns" : "shop.goods"
}

"indexName" : "spc.area_1",
"indexBounds" : {
                    "spc.area" : [ 
                        "[\"taiwan\", \"taiwan\"]"
                    ]
                }
                
                
//刚才创建的都是普通索引,
//唯一索引:这个列上的值不能重复
创建唯一索引:
db.collection.ensureIndex({filed.subfield:1/-1}, {unique:true});

db.teacher.insert({email:[email protected]})
db.teacher.insert({email:[email protected]})
db.teacher.getIndexes()
db.teacher.ensureIndex({email:1},{unique:true})                
db.teacher.getIndexes():
    {
        "v" : 2,
        "unique" : true,
        "key" : {
            "email" : 1.0
        },
        "name" : "email_1",
        "ns" : "shop.teacher"
    }
db.teacher.insert({email:[email protected]})  //插入失败,唯一索引不能重复
db.teacher.find({email:[email protected]})



//稀疏索引:
db.teacher.dropIndexes();
db.teacher.getIndexes()  //只有id索引
db.teacher.insert({})
db.find():
{
    "_id" : ObjectId("5a4748a2e4778e360cdb54bc"),"email" : "11@163.com"
}
{
    "_id" : ObjectId("5a474d4ce4778e360cdb54c4")    //根本就没有email属性
}
{
    "_id" : ObjectId("5a474d85e4778e360cdb54c5"),"email" : "22@163.com"
}
db.teacher.ensureIndex({email:1})

db.teacher.find({email:null}):   
{
    "_id" : ObjectId("5a474d4ce4778e360cdb54c4")
}
db.teacher.find({email:null}).explain()   //把email为null的也查到了(错的,是把没有email列的属性的查到了),说明把null也建立了索引(是没有email列不是email列为null,这不是表,每一行是没有关系的)


//稀疏索引,有这个列就建立索引,没有这个列就不建立索引,
db.teacher.dropIndexes()   //删除索引,建立稀疏索引
db.teacher.ensureIndex({email:1},{sparse:true});
    {
        "v" : 2,
        "key" : {
            "email" : 1.0
        },
        "name" : "email_1",
        "ns" : "shop.teacher",
        "sparse" : true
    }
db.teacher.find({email:null}).explain()     //(把没有email列的查到了)查到了,但是没有用到email索引,

/*
创建稀疏索引:
稀疏索引的特点------如果针对field做索引,针对不含field列的文档(每一行的各列没有关系),将不建立索引.
与之相对,普通索引,会把该文档的field列的值认为NULL,并建索引.
适宜于: 小部分文档含有某列时.
db.collection.ensureIndex({field:1/-1},{sparse:true});

> db.tea.find();
{ "_id" : ObjectId("5275f99b87437c610023597b"), "email" : "[email protected]" }
{ "_id" : ObjectId("5275f99e87437c610023597c"), "email" : "[email protected]" }
{ "_id" : ObjectId("5275f9e887437c610023597e"), "email" : "[email protected]" }
{ "_id" : ObjectId("5275fa3887437c6100235980") }
如上内容,最后一行没有email列,
如果分别加普通索引,和稀疏索引,
对于最后一行的email分别当成null 和 忽略最后一行来处理.
根据{email:null}来查询,前者能查到,而稀疏索引查不到最后一行. */



//哈希索引:

Btree:根据二叉树左右移动来查找。
哈希:有一个哈希函数,任意给一个值根据这个函数算,算到数据在硬盘的位置,不用查找直接算一下就可以了,时间复杂度为1,没有btree有顺序性,胡乱的查找并不快(顺序查找要快)。对于范围的查询和顺序读取要慢。
db.teacher.dropIndexes()
db.teacher.ensureIndex({email:hashed})
db.teacher.getIndexes():
    {
        "v" : 2,
        "key" : {
            "email" : "hashed"
        },
        "name" : "email_hashed",
        "ns" : "shop.teacher"
    }
db.teacher.find({email:[email protected]}).explain():
"indexName" : "email_hashed",
"indexBounds" : {
                    "email" : [ 
                        "[-8642475493292651614, -8642475493292651614]"
                    ]
                }

                
                
创建哈希索引(2.4新增的)
哈希索引速度比普通索引快,但是,无能对范围查询进行优化.
适宜于---随机性强的散列
db.collection.ensureIndex({file:’hashed’});    
            
重建索引
一个表经过很多次修改后,导致表的文件产生空洞,索引文件也如此.
可以通过索引的重建,减少索引文件碎片,并提高索引的效率.
类似mysql中的optimize table

db.collection.reIndex()   //重建之后索引还在。


db.collection.ensureIndex({field:hashed});
说明:
1. 可以单个字段或子文本字段上建立hash索引
2. 不可以针对"多个列"建立hash索引
例: db.collection.ensureIndex(intro.height:hashed);



删除指定索引:
db.collections.dropIndex({filed:1/-1/hashed});
例:
db.user.dropIndex({intro.height:hashed});
删除所有索引:
db.collection.dropIndexes();
注:_id列的索引不会被删除

 

以上是关于mongodb06---索引的主要内容,如果未能解决你的问题,请参考以下文章

Mongodb06 - 索引

唯一索引不适用于 Mongoose / MongoDB

如何将代码片段存储在 mongodb 中?

MongoDB - 如何提高创建索引的性能?

mongoDB没有选择索引

不同类型的 MongoDB 索引