欢迎登陆真网站,您的到来是我们的荣幸。 登陆 注册 忘记密码? ☆设为首页 △加入收藏
欢迎加入真幸福QQ群
电脑知识: 基础知识 网络技术 操作系统 办公软件 电脑维修 电脑安全 windows7 windows8 windows10 服务器教程 平板电脑 视频播放教程 网络应用 互联网 工具软件 浏览器教程 QQ技巧 输入法教程 影视制作 YY教程 wps教程 word教程 Excel教程 PowerPoint
云南西双版纳特产小花糯玉米真空包装


设置IIS网站独立帐号确保服务器安全
解析Linux系统安全的命令
深入解析Linux下的定时任务
Linux下一个简单的多线程互斥锁的例子
维护Windows网络服务器安全的技巧
hyper-v虚拟机转换成vmware虚拟机的方法
打deb包、创建 apt源仓库
Apache遇到的问题 APR not found问题的解决方法
Centos6.0 x64下搭建LAMP环境
如何实现在空间主机下CMS系统和wordpress同时使用
MongoDB学习笔记(六) MongoDB索引用法和效率分析
【 来源:网络 】【 点击:1 】 【 发布时间:2017_03_03 08:59:59 】

MongoDB中的索引其实类似于关系型数据库,都是为了提高查询和排序的效率的,并且实现原理也基本一致。由于集合中的键(字段)可以是普通数据 类型,也可以是子文档。MongoDB可以在各种类型的键上创建索引。下面分别讲解各种类型的索引的创建,查询,以及索引的维护等。

一、创建索引

   1. 默认索引

  MongoDB有个默认的“_id”的键,他相当于“主键”的角色。集合创建后系统会自动创建一个索引在“_id”键上,它是默认索引,索引名叫“_id_”,是无法被删除的。我们可以通过以下方式查看:

复制代码 代码如下:

var _idIndex = mongoCollection.Metadata.Indexes.Single(x => x.Key == "_id_");
Console.WriteLine(_idIndex);

2. 单列索引

  在单个键上创建的索引就是单列索引,例如我们要在“UserInfo”集合上给“UserName”键创建一个单列索引,语法如下:(1表示正序,-1逆序)

复制代码 代码如下:
mongoCollection.Metadata.CreateIndex(new Document { { "UserName", 1 } }, false);

  接着,我们用同样方法查找名为“_UserName_”的索引

复制代码 代码如下:

var _UserName_Index = mongoCollection.Metadata.Indexes.Single(x => x.Key == "_UserName_");
Console.WriteLine(_UserName_Index);

3.组合索引

  另外,我们还可以同时对多个键创建组合索引。如下代码创建了按照“UserId”正序,“UserName”逆序的组合索引:

复制代码 代码如下:
mongoCollection.Metadata.CreateIndex(new Document { { "UserId", 1 }, { "UserName", -1 } }, false);

4.子文档索引

  我们可以对文档类型的键创建各种索引,例如单列索引,如下创建用户详细信息“Detail”的单列索引:

复制代码 代码如下:
mongoCollection.Metadata.CreateIndex(new Document { { "Detail", 1 } }, false);

对子文档的键创建组合索引:例如在“Detail.Address”和“Detail.Age”上创建组合索引:

复制代码 代码如下:
mongoCollection.Metadata.CreateIndex(new Document { { "Detail.Address", 1 }, { "Detail.Age", -1 } }, false);

5.唯一索引

  唯一索引限制了对当前键添加值时,不能添加重复的信息。值得注意的是,当文档不存在指定键时,会被认为键值是“null”,所以“null”也会被认为是重复的,所以一般被作为唯一索引的键,最好都要有键值对。

  对“UserId”创建唯一索引(这时候最后一个参数为“true”):

复制代码 代码如下:
mongoCollection.Metadata.CreateIndex(new Document { { "UserId", 1 } }, true);

二、维护索引

1. 查询索引

  通过索引名查询的方式已有介绍。但有时候,我们可能忘记了索引名,怎么查询呢?

  下面提供一个遍历全部索引的方法,打印全部索引信息:

复制代码 代码如下:

foreach (var index in mongoCollection.Metadata.Indexes)
 {
     Console.WriteLine(index.Value);
}

  输出结果示例:

复制代码 代码如下:

{ "name": "_id_", "ns": "myDatabase.UserInfo", "key": { "_id": 1 } }
{ "name": "_UserId_unique_", "ns": "myDatabase.UserInfo", "key": { "UserId": 1 }, "unique": true, "_id": "4d8f406ab8a4730b78000005" }
{ "name": "_UserName_", "ns": "myDatabase.UserInfo", "key": { "UserName": 1 }, "unique": false, "_id": "4d8f406ab8a4730b78000006" }
{ "name": "_Detail.Address_Detail.Age_", "ns": "myDatabase.UserInfo", "key": { "Detail.Address": 1, "Detail.Age": -1 }, "unique": false, "_id": "4d8f406ab8a4730b78000007" }
{ "name": "_UserId_UserName_", "ns": "myDatabase.UserInfo", "key": { "UserId": 1, "UserName": -1 }, "unique": false, "_id": "4d8f406ab8a4730b78000008" }
{ "name": "_Detail_", "ns": "myDatabase.UserInfo", "key": { "Detail": 1 }, "unique": false, "_id": "4d8f406ab8a4730b78000009" }

可见,集合的索引也是通过一个集合来维护的。name表示索引名,ns表示索引属于哪个库哪个集合,key表示索引在哪个键上,正序还是逆序,unique表示是否为唯一索引,等等...

   2. 删除索引

  新手常陷入的误区是,认为集合被删除,索引就不存在了。关系型数据库中,表被删除了,索引也不会存在。在MongoDB中不存在删除集合的说法,就算集合数据清空,索引都是还在的,要移除索引还需要手工删除。

  例如,删除名为“_UserName_”的索引:

复制代码 代码如下:

mongoCollection.Metadata.DropIndex("_UserName_");

下面提供删除除默认索引外其他全部索引的方法:

复制代码 代码如下:

public void DropAllIndex()
{
    var listIndexes = mongoCollection.Metadata.Indexes.ToList();
    for (int i = 0; i < listIndexes.Count; i++)
    {
        if (listIndexes[i].Key != "_id_")
        {
            mongoCollection.Metadata.DropIndex(listIndexes[i].Key);
        }
    }
}

三、索引的效率

  MongoDB的索引到底能不能提高查询效率呢?我们在这里通过一个例子来测试。比较同样的数据在无索引和有索引的情况下的查询速度。

  首先,我们通过这样一个方法插入10W条数据:

复制代码 代码如下:

public void InsertBigData()
{
    var random = new Random();
    for (int i = 1; i < 100000; i++)
    {
        Document doc = new Document();

        doc["ID"] = i;
        doc["Data"] = "data" + random.Next(100000);

        mongoCollection.Save(doc);
    }

    Console.WriteLine("当前有" + mongoCollection.FindAll().Documents.Count() + "条数据");
}

 然后,实现一个方法用来创建索引:

复制代码 代码如下:

public void CreateIndexForData()
{
    mongoCollection.Metadata.CreateIndex(new Document { { "Data", 1 } }, false);
}

还有排序的方法:

复制代码 代码如下:
public void SortForData()
{
    mongoCollection.FindAll().Sort(new Document { { "Data", 1 } });
}

 运行测试代码如下:

复制代码 代码如下:

static void Main(string[] args)
{
    IndexBLL indexBll = new IndexBLL();
    indexBll.DropAllIndex();
    indexBll.DeleteAll();
    indexBll.InsertBigData();

    Stopwatch watch1 = new Stopwatch();
    watch1.Start();
    for (int i = 0; i < 1; i++) indexBll.SortForData();
    Console.WriteLine("无索引排序执行时间:" + watch1.Elapsed);

    indexBll.CreateIndexForData();

    Stopwatch watch2 = new Stopwatch();
    watch2.Start();
    for (int i = 0; i < 1; i++) indexBll.SortForData();
    Console.WriteLine("有索引排序执行时间:" + watch2.Elapsed);

}

最后执行程序查看结果:



多次测试表明在有索引的情况下,查询效率要高于无索引的效率。

作者:李盼(Lipan)
出处:[Lipan] (http://www.cnblogs.com/lipan/)

本网站由川南居提供技术支持,fkzxf版权所有 浙ICP备12031891号
淳安分站 淳安分站