給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表示刪除成功


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM