• 给MongoDB添加索引


     

    MongoDB入库、更新、查询效率简单测试

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/BLUE__YEAH/article/details/41679373

    单mongod测试(即只有一个mongod程序实例)

    所有测试机均为4g内存双核cpu(64位系统)

    测试所用文档为简单的三个字段的文档:

    DBObject doc = newBasicDBObject();   

                                   doc.put("test","test"+insertNum);   

                                   doc.put("no", insertNum);

                                   doc.put("time",swapWords(sld.format(new Date())));

    一、入库效率:

    1、普通集合入库,

    每10万条数据平均2~3秒

    入库一亿条数据大概45分钟

    2、四个索引的普通集合

    初始每10万条5~6秒,时间逐渐增长,到千万级别时每10万条入库时间60~80秒

    入库一千万数据一小时多一点

    3、一个索引的普通集合

    初始入库每10万条3秒左右,耗时逐渐增长,到四千万左右时每10万条入库时间15~20秒

    入库一千万数据7、8分钟

    入库四千万数据大概一个半小时

    4、固定集合

    初始入库每10万条数据平均2~2.5秒

    5、一个索引的固定集合

    初始入库每10万条数据平均3~4秒

    二、查询效率:

    没有索引会进行表扫描(大表会极慢)

    无论有没有索引,大批量插入时查询效率极慢

    三、插入时机器负载:

    没索引时:cpu不到20%

    有索引时,初始插入cpu 20,30~40,后期比较慢不到5~15% 猜测原因内存已经用满,磁盘io比较多

             mongos测试(三台机器的简单无备份mongod分片群)

    一、简单入库

    1、test集合,分片,无索引,文档结构大小同上例

    每10万条记录 3~3.5秒

                                                  

    从sqlserver测试表导数据至mongos(三台)测试

    一、第一种入库策略:

    先入库,再建索引及分片,按索引分片

    1、测试表Test共20列1.5亿数据

    2、导到mongos时表不设索引,不分片,等到入库完毕后再进行这些操作

    3、导出时所有列都用的string

    4、1亿5千万入库6个半小时  10万/10~20秒(从远程的sqlserver数据库导入,一边遍历结果集一边插入,所以实际入库速度应该比这个快)

    5、建userid,city的二级索引大概用了半个小时(从日志中查看)

    6、按索引中(userid,city)的一个键分片(而不是用objectid);

    操作是阻塞式的,吃完饭回来就完成了。。应该是在一个半小时内

    7、在有分片及索引的情况下,追加插入效率较差,每1000条 20~30秒

    8、所以考虑:撤销索引,查看集合行数(看是否有影响),追加插入数据,建立索引,测试查询。但是刚刚撤销索集群就无法访问了(因为分片是按索引userid分的).

    二、查询:

    建立索引后:

    几次测试,同一个程序10000条数据连续查询,平均11~13毫秒

    并发测试,3个程序同时分别连续查询10000条数据,平均14毫秒

    三、删除集合不会释放硬盘空间

    1、删除后的表不会释放硬盘空间而是内部标记为空闲,需要注意

    2、可以用db.repairDatabase()整理磁盘文件:

    mongos会分mongod分别处理,每个mongod处理自己的

    程序首先会将所有有效数据写入临时文件(在他的文件系统中发现诸如_tmp等文件中数据文件增加很多,而且其中文件格式和源数据文件格式相似),所以硬盘占用率会很明显的上升,完成整理后硬盘占用减少。

    3、所以如果使用此方法:

    应该保证磁盘剩余空间容量>mongodb数据文件中有效数据量,

    保险方法是磁盘剩余空间>mongodb数据文件

    4、时间

    比较慢,不到180g有效数据分在三台机器,用了1~3个小时

    4、在此过程中查询:

    在此过程中读写几乎不能用

    四、第二种入库策略:

    按objectid分片,索引及入库策略不变

    1、  初始入库时间大致和之前相同(1.5亿条数据)

    2、  追加存入重复数据

    20万条10分钟(先遍历sqlserver结果集存入内存中再一次性入库mongodb)

    3、  追加新数据入库

    20万条2分半钟(先遍历sqlserver结果集存入内存中再一次性入库mongodb)

    4、  根据非objectid键更新插入(upsert)

    很慢,1000条需要6~8分钟(实际上操作失败,因为upsert操作需要指定分片键objectid)

    5、  查询

    速度比之前方案稍慢,35~40毫秒平均(连续查询20000次)

                                                             其他

    1、  windows,linux混合集群测试       

    可行,效率没大规模用过,不知道是否稳定。Linux方面程序不会主动释放内存,windows程序据观察在入库时内存占用量增大,但是入库完后会释放。

    2、  32位windows系统程序确实只能存2g数据,大于2g数据后程序报错退出。

    MongoDB索引管理-索引的创建、查看、删除

     

    http://itbilu.com/database/mongo/E1tWQz4_e.html

    索引是提高查询查询效率最有效的手段。索引是一种特殊的数据结构,索引以易于遍历的形式存储了数据的部分内容(如:一个特定的字段或一组字段值),索引会按一定规则对存储值进行排序,而且索引的存储位置在内存中,所在从索引中检索数据会非常快。如果没有索引,MongoDB必须扫描集合中的每一个文档,这种扫描的效率非常低,尤其是在数据量较大时。

    1. 创建/重建索引
    2. 查看索引
    3. 删除索引

    1. 创建/重建索引

    MongoDB全新创建索引使用ensureIndex()方法,对于已存在的索引可以使用reIndex()进行重建。

    1.1 创建索引ensureIndex()

    MongoDB创建索引使用ensureIndex()方法。

    语法结构

    db.COLLECTION_NAME.ensureIndex(keys[,options])
    • keys,要建立索引的参数列表。如:{KEY:1},其中key表示字段名,1表示升序排序,也可使用使用数字-1降序。
    • options,可选参数,表示建立索引的设置。可选值如下:
      • background,Boolean,在后台建立索引,以便建立索引时不阻止其他数据库活动。默认值 false。
      • unique,Boolean,创建唯一索引。默认值 false。
      • name,String,指定索引的名称。如果未指定,MongoDB会生成一个索引字段的名称和排序顺序串联。
      • dropDups,Boolean,创建唯一索引时,如果出现重复删除后续出现的相同索引,只保留第一个。
      • sparse,Boolean,对文档中不存在的字段数据不启用索引。默认值是 false。
      • v,index version,索引的版本号。
      • weights,document,索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。

    如,为集合sites建立索引:

    > db.sites.ensureIndex({name: 1, domain: -1})
    {
      "createdCollectionAutomatically" : false,
      "numIndexesBefore" : 1,
      "numIndexesAfter" : 2,
      "ok" : 1
    }

    注意:1.8版本之前创建索引使用createIndex()1.8版本之后已移除该方法

    1.2 重建索引reIndex()

    db.COLLECTION_NAME.reIndex()

    如,重建集合sites的所有索引:

    > db.sites.reIndex()
    {
      "nIndexesWas" : 2,
      "nIndexes" : 2,
      "indexes" : [
        {
    	  "key" : {
    		"_id" : 1
    	  },
    	  "name" : "_id_",
    		"ns" : "newDB.sites"
    	},
    	{
    	  "key" : {
    		"name" : 1,
    		"domain" : -1
    	  },
    	  "name" : "name_1_domain_-1",
    	  "ns" : "newDB.sites"
    	}
      ],
      "ok" : 1
    }

    2. 查看索引

    MongoDB提供了查看索引信息的方法:getIndexes()方法可以用来查看集合的所有索引,totalIndexSize()查看集合索引的总大小,db.system.indexes.find()查看数据库中所有索引信息。

    2.1 查看集合中的索引getIndexes()

    db.COLLECTION_NAME.getIndexes()

    如,查看集合sites中的索引:

    >db.sites.getIndexes()
    [
      {
    	"v" : 1,
    	"key" : {
    	  "_id" : 1
    	},
    	"name" : "_id_",
    	"ns" : "newDB.sites"
      },
      {
    	"v" : 1,
    	"key" : {
    	  "name" : 1,
    	  "domain" : -1
    	},
    	"name" : "name_1_domain_-1",
    	"ns" : "newDB.sites"
      }
    ]

    2.2 查看集合中的索引大小totalIndexSize()

    db.COLLECTION_NAME.totalIndexSize()

    如,查看集合sites索引大小:

    > db.sites.totalIndexSize()
    16352

    2.3 查看数据库中所有索引db.system.indexes.find()

    db.system.indexes.find()

    如,当前数据库的所有索引:

    > db.system.indexes.find()

    3. 删除索引

    不在需要的索引,我们可以将其删除。删除索引时,可以删除集合中的某一索引,可以删除全部索引。

    3.1 删除指定的索引dropIndex()

    db.COLLECTION_NAME.dropIndex("INDEX-NAME")

    如,删除集合sites中名为"name_1_domain_-1"的索引:

    > db.sites.dropIndex("name_1_domain_-1")
    { "nIndexesWas" : 2, "ok" : 1 }

    3.3 删除所有索引dropIndexes()

    db.COLLECTION_NAME.dropIndexes()

    如,删除集合sites中所有的索引:

    > db.sites.dropIndexes()
    {
      "nIndexesWas" : 1,
      "msg" : "non-_id indexes dropped for collection",
      "ok" : 1
    }

     

    用过数据库的都知道,数据库索引与书籍的索引类似,都是用来帮助快速查找的。
     
    MongoDB的索引跟关系型数据库的索引几乎一致。
     
     
     
    1. 索引的创建
     
    mongodb采用ensureIndex来创建索引,如:
     
    db.user.ensureIndex({"name":1})
     
    表示在user集合的name键创建一个索引,这里的1表示索引创建的方向,可以取值为1和-1
     
    在这里面,我们没有给索引取名字,mongodb会为我们取一个默认的名字,规则为keyname1_dir1_keyname2_dir2...keynameN_dirN
     
    keyname表示键名,dir表示索引的方向,例如,上面的例子我们创建的索引名字就是name_1
     
     
     
    索引还可以创建在多个键上,也就是联合索引,如:
     
    > db.user.ensureIndex({"name":1,"age":1})
     
    这样就创建了name和age的联合索引
     
     
     
    除了让mongodb默认索引的名字外,我们还可以去一个方便记的名字,方法就是为ensureIndex指定name的值,如:
     
    > db.user.ensureIndex({"name":1},{"name":"IX_name"})
     
    这样,我们创建的索引的名字就叫IX_name了
     
     
     
    2. 唯一索引
     
    与RDB类似,我们也可以定义唯一索引,方法就是指定unique键位true:
     
    >db.user.ensureIndex({"name":1},{"unique":true})
     
     
     
    3.查看我们建立的索引
     
    索引的信息存在每个数据库的system.indexes集合里面,对这个集合只能有ensureIndex和dropIndexes进行修改,不能手动插入或修改集合。
     
    通过> db.system.indexes.find()可以找到数据库中多有的索引:
     
    > db.system.indexes.find() 
    { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.entities", "name" : "_id_" } 
    { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.blog", "name" : "_id_" } 
    { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.authors", "name" : "_id_" } 
    { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.papers", "name" : "_id_" } 
    { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.analytics", "name" : "_id_" } 
    { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.user", "name" : "_id_" } 
    { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.food", "name" : "_id_" } 
    { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.user.info", "name" : "_id_" } 
    { "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.userinfo", "name" : "_id_" } 
    { "v" : 1, "key" : { "name" : 1 }, "ns" : "test.user", "name" : "IX_name" }
     
     
     
    4.删除索引
     
    如果索引没有用了,可以使用dropIndexes将其删掉:
     
    > db.runCommand({"dropIndexes":"user","index":"IX_name"}) 
    { "nIndexesWas" : 2, "ok" : 1 }
     
    ok表示删除成功
  • 相关阅读:
    A1023 Have Fun with Numbers [大整数乘法]
    大整数的四则运算
    A1096 Consecutive Factors [因子分解]
    A1078 Hashing [质数和散列结合]
    A1015 Reversible Primes [质数问题]
    又谈进制转换
    A1088 Rational Arithmetic [分数四则运算]
    A1081 Rational Sum [分数计算]
    linux主流系统配置静态ip
    主机ping虚拟机请求超时,虚拟机ping主机正常ping通导致ssh连接问题
  • 原文地址:https://www.cnblogs.com/williamjie/p/9767245.html
Copyright © 2020-2023  润新知