MongoDB 索引创建

在数据量超大的情形下,任何数据库系统在创建索引时都是一个耗时的大工程。MongoDB也不例外。因此,MongoDB索引的创建有两个选择,一个是前台方式,一个是后台方式。那这两种方式有什么差异呢,在创建索引是是否能观察到索引完成的进度呢。本文将是基于此的描述,同时也描述了索引创建相关的注意事项。

一、索引创建方式

    前台方式
            缺省情况下,当为一个集合创建索引时,这个操作将阻塞其他的所有操作。即该集合上的无法正常读写,直到索引创建完毕
            任意基于所有数据库申请读或写锁都将等待直到前台完成索引创建操作

    后台方式
            将索引创建置于到后台,适用于那些需要长时间创建索引的情形
            这样子在创建索引期间,MongoDB依旧可以正常的为提供读写操作服务
            等同于关系型数据库在创建索引的时候指定online,而MongoDB则是指定background
            其目的都是相同的,即在索引创建期间,尽可能的以一种占用较少的资源占用方式来实现,同时又可以提供读写服务
            后台创建方式的代价:索引创建时间变长

    后台创建索引的示例
            db.people.createIndex( { zipcode: 1}, {background: true} )
            db.people.createIndex( { city: 1}, {background: true, sparse: true } )

    缺省情况下background选项的值为false

二、索引创建期间注意事项

    如前所述,基于后台创建索引时,其他的数据库操作能被完成。但是对于mongo shell会话或者你正在创建索引的这个连接
    将不可用,直到所有创建完毕。如果需要做一些其它的操作。则需要再建立其它的连接。

    在索引创建期间,即使完成了部分索引的创建,索引依旧不可用,但是一旦创建完成即可使用。

    基于后台创建索引期间不能完成涉及该集合的相关管理操作
            repairDatabase
            db.collection.drop()
            compact

    意外中断索引创建
            如果在后台创建索引期间,mongod实例异常终止,当mongod实例重新启动后,未完成的索引创建将作为前台进程来执行
            如果索引创建失败,比如由于重复的键等,mongod将提示错误并退出
            在一个索引创建失败后启动mongod,可以使用storage.indexBuildRetry or --noIndexBuildRetry跳过索引创建来启动

三、索引创建期间性能

    后台创建索引比前台慢,如果索引大于实际可用内存,则需要更长的时间来完成索引创建
    所有涉及到该集合的相关操作在后台期间其执行效能会下降,应在合理的维护空挡期完成索引的创建

四、索引的命名规则

    缺省情况下,索引名以键名加上其创建顺序(1或者-1)组合而成。
    db.products.createIndex( { item: 1, quantity: -1 } )
    比如上面的索引创建后,其索引名为item_1_quantity_-1
    可以指定自定义的索引名称

    db.products.createIndex( { item: 1, quantity: -1 } , { name: "inventory_idx" } )

    如上方式,我们指定了了索引名称为inventory_idx

五、查看索引创建进度

    可使用 db.currentOp() 命令观察索引创建的完成进度

            > db.currentOp(
        {
          $or: [
            { op: "command", "query.createIndexes": { $exists: true } },
            { op: "insert", ns: /\.system\.indexes\b/ }
          ]
        }
        )

        //下面通过一个索引创建示例来查看索引完成进度
        //首选创建一个500w文档的集合

        > db.version()       // Author : Leshami
        3.2.10             // Blog   : http://blog.csdn.net/leshami 

        > for (var i=1;i<=5000000;i++){
          db.inventory.insert({id:i,item:"item"+i,stock:Math.floor(i*Math.random())})
          }
        WriteResult({ "nInserted" : 1 })

        > db.inventory.find().limit(3)
        { "_id" : ObjectId("581bfc674b0d633653f4427e"), "id" : 1, "item" : "item1", "stock" : 0 }
        { "_id" : ObjectId("581bfc674b0d633653f4427f"), "id" : 2, "item" : "item2", "stock" : 0 }
        { "_id" : ObjectId("581bfc674b0d633653f44280"), "id" : 3, "item" : "item3", "stock" : 1 }

        > db.inventory.find().count()
        5000000

        //下面开始创建索引
        > db.inventory.createIndex({item:1,unique:true})

        //使用下面的命令查看索引完成进度
            > db.currentOp(
                {
                  $or: [
                    { op: "command", "query.createIndexes": { $exists: true } },
                    { op: "insert", ns: /\.system\.indexes\b/ }
                  ]
                }
            )

        //结果如下
        {
                "inprog" : [
                        {
                                "desc" : "conn1",                 //连接描述
                                "threadId" : "139911670933248",   //线程id
                                "connectionId" : 1,
                                "client" : "127.0.0.1:37524",     //ip及端口
                                "active" : true,                  //活动状态
                                "opid" : 5014925,
                                "secs_running" : 21,              //已执行的时间
                                "microsecs_running" : NumberLong(21800738),
                                "op" : "command",
                                "ns" : "test.$cmd",
                                "query" : {
                                        "createIndexes" : "inventory", //这里描述了基于inventory正在创建索引
                                        "indexes" : [
                                                {
                                                        "ns" : "test.inventory",
                                                        "key" : {
                                                                "item" : 1,
                                                                "unique" : true
                                                        },
                                                        "name" : "item_1_unique_true"
                                                }
                                        ]
                                },
                                "msg" : "Index Build Index Build: 3103284/5000000 62%",  //这里是完成的百分比
                                "progress" : {
                                        "done" : 3103722,
                                        "total" : 5000000
                                },
                                "numYields" : 0,
                                "locks" : {                  //当前持有的锁
                                        "Global" : "w",
                                        "Database" : "W",
                                        "Collection" : "w"
                                },
                                "waitingForLock" : false,
                                "lockStats" : {              //锁的状态信息
                                        "Global" : {
                                                "acquireCount" : {
                                                        "r" : NumberLong(1),
                                                        "w" : NumberLong(1)
                                                }
                                        },
                                        "Database" : {
                                                "acquireCount" : {
                                                        "W" : NumberLong(1)
                                                }
                                        },
                                        "Collection" : {
                                                "acquireCount" : {
                                                        "w" : NumberLong(1)
                                                }
                                        }
                                }
                        }
                ],
                "ok" : 1
        }

    //基于后台方式创建索引

    > db.inventory.createIndex({item:1,unique:true},{background: true})

六、终止索引的创建

    db.killOp()

七、更多参考
MongoDB 单键(列)索引
MongoDB 复合索引
MongoDB 多键索引
MongoDB 执行计划获取(db.collection.explain())
MongoDB 唯一索引
MongoDB 部分索引
MongoDB 稀疏(间隙)索引(Sparse Indexes)

时间: 2024-08-01 15:53:44

MongoDB 索引创建的相关文章

Mongodb后台创建索引的问题

后台创建索引,遍历Collection表的所有数据之前,会先把数据库的锁从MODE_X变成MODE_IX, (关于数据库多级锁的概念,https://en.wikipedia.org/wiki/Multiple_granularity_locking), 从而允许其他客户端对数据库读写操作.一面做全表扫面,一面做数据的更新,如果保证索引和数据能对的上呢? 事实上Mongodb是不提供事务保证的,只对单个文档的操作提供了原子操作保证,所以如果执行一个update多个值的操作,不能保证要更新的多个值

MongoDB索引原理

MongoDB索引原理 为什么需要索引? 当你抱怨MongoDB集合查询效率低的时候,可能你就需要考虑使用索引了,为了方便后续介绍,先科普下MongoDB里的索引机制(同样适用于其他的数据库比如mysql). mongo-9552:PRIMARY> db.person.find() { "_id" : ObjectId("571b5da31b0d530a03b3ce82"), "name" : "jack", "

详解MongoDB中创建集合与删除集合的操作方法_MongoDB

创建集合:createCollection() 方法 MongoDB db.createCollection(name, options)  是用来创建集合. 语法: 基本的 createCollection() 命令语法如下: db.createCollection(name, options) 在命令中, name 是要创建的集合的名称. Options 是一个文件,用于指定配置的集合 参数 类型 描述 Name String 要创建的集合名称 Options Document (可选)指定

MongoDB索引使用详解_MongoDB

索引就像书的目录,如果查找某内容在没有目录的帮助下,只能全篇查找翻阅,这导致效率非常的低下:如果在借助目录情况下,就能很快的定位具体内容所在区域,效率会直线提高. 索引简介 首先打开命令行,输入mongo.默认mongodb会连接名为test的数据库. ➜ ~ mongo MongoDB shell version: 2.4.9 connecting to: test > show collections > 可以使用show collections/tables查看数据库为空. 然后在mon

MongoDB索引的学习笔记

一.索引基础: MongoDB的索引几乎与传统的关系型数据库一模一样,这其中也包括一些基本的优化技巧.下面是创建索引的命令: > db.test.ensureIndex({"username":1}) 可以通过下面的名称查看索引是否已经成功建立: > db.test.getIndexes() 删除索引的命令是: > db.test.dropIndex({"username":1}) 在MongoDB中,我们同样可以创建复合索引,如: - 数字1表示

MySQL 5.7 : 索引创建优化(Bulk Load)

先来看一组测试数据 使用sysbench,生成一张大约10,000,000行记录的表,数据全部在buffer pool中 创建索引(k,pad) 5.7.5 alter table sbtest1 add key(k,pad); Query OK, 0 rows affected (44.14 sec) Records: 0  Duplicates: 0  Warnings: 0 5.7.4 root@sbb 04:25:11>alter table sbtest1 add key(k,pad)

mysql 优化实例之索引创建

mysql 优化实例之索引创建 优化前: pt-query-degist分析结果: # Query 23: 0.00 QPS, 0.00x concurrency, ID 0x78761E301CC7EE47 at byte 394687 # This item is included in the report because it matches --limit. # Scores: V/M = 3.27 # Time range: 2016-09-29T11:46:22 to 2016-1

MongoDB中创建索引需要注意的事项_MongoDB

上周在 ruby-china 上发了帖子<MongoDB 那些坑>,反映相当热烈,许多回复很有见地,其中一位童鞋深入的提到 MongoDB 建索引方法的问题,引发我更深入的了解了 MongoDB 建索引的方法和一些注意事项. 在 <MongoDB 那些坑>中提到,在前台直接运行建立索引命令的话,将造成整个数据库阻塞,因此索引建议使用 background 的方式建立.但是这也会带来一定的问题,在 2.6 版本之前,在 secondary server 中即使使用 backgroun

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

MongoDB中的索引其实类似于关系型数据库,都是为了提高查询和排序的效率的,并且实现原理也基本一致.由于集合中的键(字段)可以是普通数据 类型,也可以是子文档.MongoDB可以在各种类型的键上创建索引.下面分别讲解各种类型的索引的创建,查询,以及索引的维护等. 一.创建索引 1. 默认索引 MongoDB有个默认的"_id"的键,他相当于"主键"的角色.集合创建后系统会自动创建一个索引在"_id"键上,它是默认索引,索引名叫"_id