• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當前位置: 首頁 - 科技 - 知識百科 - 正文

    關于mongodb創建索引的一些經驗總結

    來源:懂視網 責編:小采 時間:2020-11-09 15:02:09
    文檔

    關于mongodb創建索引的一些經驗總結

    關于mongodb創建索引的一些經驗總結:想來接觸mongodb已經快一年了,對于它的索引知識也積攢了不少經驗,趁著這個月黑風高的夜晚,就把mongodb的索引總結一番吧。 一,索引介紹 mongodb具有兩類索引,分別為單鍵索引和復合索引。 1.單鍵索引是最簡單的一種索引,創建單鍵索引的開銷要比復合索引
    推薦度:
    導讀關于mongodb創建索引的一些經驗總結:想來接觸mongodb已經快一年了,對于它的索引知識也積攢了不少經驗,趁著這個月黑風高的夜晚,就把mongodb的索引總結一番吧。 一,索引介紹 mongodb具有兩類索引,分別為單鍵索引和復合索引。 1.單鍵索引是最簡單的一種索引,創建單鍵索引的開銷要比復合索引

    想來接觸mongodb已經快一年了,對于它的索引知識也積攢了不少經驗,趁著這個月黑風高的夜晚,就把mongodb的索引總結一番吧。 一,索引介紹 mongodb具有兩類索引,分別為單鍵索引和復合索引。 1.單鍵索引是最簡單的一種索引,創建單鍵索引的開銷要比復合索引

    想來接觸mongodb已經快一年了,對于它的索引知識也積攢了不少經驗,趁著這個月黑風高的夜晚,就把mongodb的索引總結一番吧。

    一,索引介紹


    mongodb具有兩類索引,分別為單鍵索引和復合索引。

    1.單鍵索引是最簡單的一種索引,創建單鍵索引的開銷要比復合索引小很多。單鍵索引主要用于針對單值查詢的條件。

    2.復合索引是將文檔中的幾個鍵聯合起來創建的一種索引,創建這種索引需要更多的空間與性能開銷。分別體現在:

    1).在給大量數據創建復合索引時,會阻塞數據庫的查詢,更不用說修改和插入操作了;

    2).插入一條數據時,要花費更多的時間來給復合索引加數據;

    3).創建的復合索引所站得空間大小根據數據的類型以及鍵的數量而有所不同。比如,如果你用五個NumberInt的鍵創建的復合索引的空間大小,并不會比兩個NumberInt和一個String類型創建的復合索引占用更多的空間。索引在設計數據類型時,盡量將數據類型設置為NumberInt類型,以及盡量少使用string類型的數據做索引;

    二,創建索引


    創建索引的語句很簡單。

    1.單鍵索引的創建:db.test.ensureIndex({name:1},{name:'index_name'})

    2.復合索引的創建:db.test.ensureIndex({name:1,age:1,sex:1},{name:'index_nas'})

    三,索引優化


    索引的優化是一個重頭戲,需要詳細的來解釋。我得測試數據插入了100萬條。字段分別為name,sex,type,time,id

    1.我們來看一個簡單的查詢:db.test.find({name:'name_1'}) 相信大家對這個查詢已經很熟悉了,然后我們來看看這個語句的索引執行計劃:

    {
    	"cursor" : "BasicCursor", 查詢語句所用到的索引,而BasicCursor代表沒有索引
    	"isMultiKey" : false, 是否為復合索引
    	"n" : 1, 查詢到的結果數
    	"nscannedObjects" : 1000000, 掃描的文檔數量
    	"nscanned" : 1000000, 掃面的索引數量
    	"nscannedObjectsAllPlans" : 1000000, //影響的所有的被掃描文檔的總數量
    	"nscannedAllPlans" : 1000000, //所有被掃描的索引的總數量
    	"scanAndOrder" : false, 是否排序
    	"indexOnly" : false,
    	"nYields" : 2,
    	"nChunkSkips" : 0,
    	"millis" : 342, 花費的時間
    	"indexBounds" : {
    	
    	},
    	"server" : "node1:27017"
    }

    從這個執行計劃中可以看出,該條查詢語句查詢一條數據需要掃描整個表,這肯定扯淡了嘛,那這時候就該給這個字段創建索引了,創建一個單鍵索引

    db.test.ensureIndex({name:1},{name:'index_name'})

    創建完索引之后,再來查看看這條查詢語句的執行計劃:

    {
    	"cursor" : "BtreeCursor index_name",
    	"isMultiKey" : false,
    	"n" : 1,
    	"nscannedObjects" : 1,
    	"nscanned" : 1,
    	"nscannedObjectsAllPlans" : 1,
    	"nscannedAllPlans" : 1,
    	"scanAndOrder" : false,
    	"indexOnly" : false,
    	"nYields" : 0,
    	"nChunkSkips" : 0,
    	"millis" : 0,
    	"indexBounds" : {
    	"name" : [
    	[
    	"name_1",
    	"name_1"
    	]
    	]
    	},
    	"server" : "node1:27017"
    }

    簡直是逆天啊,nscanned和nscannedObjects居然從100萬下降到1條,也就是查詢數據時,只掃描了一條就已經找到,而且花費的時間是0秒,沒有創建索引時,居然是342毫秒,絕對索引威武啊。

    2.這時候我想通過type和sex來組合查詢某一條件的數據: db.test.find({type:1,sex:0}) 看看這句的執行計劃:

    {
    	"cursor" : "BasicCursor",
    	"isMultiKey" : false,
    	"n" : 55555,
    	"nscannedObjects" : 1000000,
    	"nscanned" : 1000000,
    	"nscannedObjectsAllPlans" : 1000000,
    	"nscannedAllPlans" : 1000000,
    	"scanAndOrder" : false,
    	"indexOnly" : false,
    	"nYields" : 0,
    	"nChunkSkips" : 0,
    	"millis" : 529,
    	"indexBounds" : {
    	
    	},
    	"server" : "node1:27017"
    }

    從這個計劃中可以看出,為了查找幾萬條數據,它也掃描了整個表,很顯然,該創建索引了:

    db.test.ensureIndex({type:1,sex:1},{name:'index_ts'})

    創建完索引之后,再來執行查詢語句,看看執行計劃:

    db.test.find({type:1,sex:0}).explain()
    {
    	"cursor" : "BtreeCursor index_ts",
    	"isMultiKey" : false,
    	"n" : 55555,
    	"nscannedObjects" : 55555,
    	"nscanned" : 55555,
    	"nscannedObjectsAllPlans" : 55555,
    	"nscannedAllPlans" : 55555,
    	"scanAndOrder" : false,
    	"indexOnly" : false,
    	"nYields" : 0,
    	"nChunkSkips" : 0,
    	"millis" : 112,
    	"indexBounds" : {
    	"type" : [
    	[
    	1,
    	1
    	]
    	],
    	"sex" : [
    	[
    	0,
    	0
    	]
    	]
    	},
    	"server" : "node1:27017"
    }

    很顯然,絕對是一個最佳索引,因為n=nscannedObjects=nscanned了,而且查詢時間從529毫秒下降到112毫秒了,這也是一個質的飛躍,可以明顯的看到,它使用了剛剛創建的index_ts索引。

    現在我又有一個需求了,我想通過時間再來排序,好的,我們執行查詢語句: db.test.find({type:1,sex:0}).sort({time:-1}) 我們來看看這個查詢語句的執行計劃:

    {
    	"cursor" : "BtreeCursor index_ts",
    	"isMultiKey" : false,
    	"n" : 55555,
    	"nscannedObjects" : 1000000,
    	"nscanned" : 1000000,
    	"nscannedObjectsAllPlans" : 1000000,
    	"nscannedAllPlans" : 1000000,
    	"scanAndOrder" : true,
    	"indexOnly" : false,
    	"nYields" : 1,
    	"nChunkSkips" : 0,
    	"millis" : 695,
    	"indexBounds" : {
    	"type" : [
    	[
    	1,
    	1
    	]
    	],
    	"sex" : [
    	[
    	0,
    	0
    	]
    	]
    	},
    	"server" : "node1:27017"
    }

    看到沒,這個查詢語句跟上一個創建索引之后的查詢出來的結果相差還是很大的,scanAndOrder和millis,時間花費了將近700毫秒,而且在查詢完畢之后還要排序,這也太不近人情了,就加了一個排序操作,怎么會讓它從白天鵝變成丑小鴨了呢?啊,關鍵參數就是scanAndOrder,意思就是在內存中把結果排序了嘛,那好啊,既然你如此薄情,那我就建個復合索引來對抗: db.test.ensureIndex({type:1,sex:1,time:-1},{name:'index_tst'})

    {
    	"cursor" : "BtreeCursor index_tst",
    	"isMultiKey" : false,
    	"n" : 55555,
    	"nscannedObjects" : 55555,
    	"nscanned" : 55555,
    	"nscannedObjectsAllPlans" : 55555,
    	"nscannedAllPlans" : 55555,
    	"scanAndOrder" : false,
    	"indexOnly" : false,
    	"nYields" : 0,
    	"nChunkSkips" : 0,
    	"millis" : 126,
    	"indexBounds" : {
    	"type" : [
    	[
    	1,
    	1
    	]
    	],
    	"sex" : [
    	[
    	0,
    	0
    	]
    	],
    	"time" : [
    	[
    	{
    	"$maxElement" : 1
    	},
    	{
    	"$minElement" : 1
    	}
    	]
    	]
    	},
    	"server" : "node1:27017"
    }

    看到了嗎?各種參數又回到最佳狀態了。這時候可能有人會問了,為什么要把time放到索引的最后而不是其它位置呢?其實這在創建索引時是有要求的,即:

    1. 將等值索引放在最前面

    2. 盡量將排序字段放在范圍字段的前面

    3. $nin和$ne跟索引沒有關系

      接下來我們再給查詢語句加條件: db.test.find({type:1,sex:0,id:{$gt:1,$lt:500000}}) 執行計劃如下:

      {
      	"cursor" : "BasicCursor",
      	"isMultiKey" : false,
      	"n" : 55555,
      	"nscannedObjects" : 1000000,
      	"nscanned" : 1000000,
      	"nscannedObjectsAllPlans" : 1000000,
      	"nscannedAllPlans" : 1000000,
      	"scanAndOrder" : false,
      	"indexOnly" : false,
      	"nYields" : 2,
      	"nChunkSkips" : 0,
      	"millis" : 553,
      	"indexBounds" : {
      	
      	},
      	"server" : "node1:27017"
      }

      可以看到,只返回兩萬多條數據,但是卻掃描了整個表,這肯定是很蛋疼的事情嘛,索引走起:

      db.test.ensureIndex({type:1,sex:1,id:1},{name:'index_tis'})

      {
      	"cursor" : "BtreeCursor index_tis",
      	"isMultiKey" : false,
      	"n" : 55555,
      	"nscannedObjects" : 55555,
      	"nscanned" : 55555,
      	"nscannedObjectsAllPlans" : 55555,
      	"nscannedAllPlans" : 55555,
      	"scanAndOrder" : false,
      	"indexOnly" : false,
      	"nYields" : 1,
      	"nChunkSkips" : 0,
      	"millis" : 137,
      	"indexBounds" : {
      	"type" : [
      	[
      	1,
      	1
      	]
      	],
      	"sex" : [
      	[
      	0,
      	0
      	]
      	],
      	"id" : [
      	[
      	1,
      	1000000
      	]
      	]
      	},
      	"server" : "node1:27017"
      }

      很顯然,這是個非常不錯的組合索引,那為何不把id放在其它地方,偏偏放在最后面呢?因為在mongodb中,索引是從左到右執行的,因此顯然要從左到右一次過濾最大數量的數據顯然type和sex的組合過濾數據量要比id高更多,因為id的忙查率要遠高于這兩個組合。

      接著再把按time排序加上,查詢:db.test.find({type:1,sex:1,id:{$gt:0,$lt:1000000}}).sort({time:-1}).explain()

      {
      	"cursor" : "BasicCursor",
      	"isMultiKey" : false,
      	"n" : 55556,
      	"nscannedObjects" : 1000000,
      	"nscanned" : 1000000,
      	"nscannedObjectsAllPlans" : 1000000,
      	"nscannedAllPlans" : 1000000,
      	"scanAndOrder" : true,
      	"indexOnly" : false,
      	"nYields" : 1,
      	"nChunkSkips" : 0,
      	"millis" : 725,
      	"indexBounds" : {
      	
      	},
      	"server" : "node1:27017"
      }

      可以看到,這個查詢語句也是極其慢的,而且還要再內存中排序,所以肯定要創建索引了:

      db.test.ensureIndex({type:1,sex:1,id:1,time:-1},{name:'index_tist'}) 我們先這樣創建索引,看看執行計劃:

      {
      	"cursor" : "BtreeCursor index_tist",
      	"isMultiKey" : false,
      	"n" : 55556,
      	"nscannedObjects" : 55556,
      	"nscanned" : 55556,
      	"nscannedObjectsAllPlans" : 55657,
      	"nscannedAllPlans" : 55657,
      	"scanAndOrder" : true,
      	"indexOnly" : false,
      	"nYields" : 0,
      	"nChunkSkips" : 0,
      	"millis" : 404,
      	"indexBounds" : {
      	"type" : [
      	[
      	1,
      	1
      	]
      	],
      	"sex" : [
      	[
      	1,
      	1
      	]
      	],
      	"id" : [
      	[
      	0,
      	1000000
      	]
      	],
      	"time" : [
      	[
      	{
      	"$maxElement" : 1
      	},
      	{
      	"$minElement" : 1
      	}
      	]
      	]
      	},
      	"server" : "node1:27017"
      }

      看到了沒有,雖然查詢時間縮短了,但是這個查詢結果還是會排序結果,好,我們再把索引改改:

      db.test.ensureIndex({type:1,sex:1,time:-1,id:1},{name:'index_tist'})

      {
      	"cursor" : "BtreeCursor index_tist",
      	"isMultiKey" : false,
      	"n" : 55556,
      	"nscannedObjects" : 55556,
      	"nscanned" : 55556,
      	"nscannedObjectsAllPlans" : 55657,
      	"nscannedAllPlans" : 55657,
      	"scanAndOrder" : false,
      	"indexOnly" : false,
      	"nYields" : 0,
      	"nChunkSkips" : 0,
      	"millis" : 168,
      	"indexBounds" : {
      	"type" : [
      	[
      	1,
      	1
      	]
      	],
      	"sex" : [
      	[
      	1,
      	1
      	]
      	],
      	"time" : [
      	[
      	{
      	"$maxElement" : 1
      	},
      	{
      	"$minElement" : 1
      	}
      	]
      	],
      	"id" : [
      	[
      	0,
      	1000000
      	]
      	]
      	},
      	"server" : "node1:27017"
      }

      再來看看,快到什么程度了,這個查詢的速度和參數條件已經比上一個索引的快了很多,那為什么會出現這種情況呢?為什么time在id的前后會有不同的表現?這是因為通過type和sex字段過濾完之后,已經在內存中有了數據,而這些數據下一步需要怎么辦?是先通過id來篩選,還是按照排序篩選呢?這里有一個知識點,在把id放在time前面時,程序首先會取復合id值,然后再把復合的數據排序,但是如果id放在排序的后面,那么程序將直接通過順序掃描索引樹的方式取出復合id范圍的數據。

      四,總結


      1.mongodb創建索引難點在于排序和范圍查詢的字段位置選擇

      2.mongodb的復合索引的索引截取查詢是順序的,即如果(a:1,b:1,c:1},則可以是查詢{a:1},{a:1,b:1},{a:1,b:1,c:1}中得任何一種都會使用該索引,其它查詢情況將不會用到該索引;

      3.盡量創建更少的索引以提高數據庫性能

      4.以上的索引優化只是生產環境的一部分,具體情況可能還要看自己的業務來定

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    關于mongodb創建索引的一些經驗總結

    關于mongodb創建索引的一些經驗總結:想來接觸mongodb已經快一年了,對于它的索引知識也積攢了不少經驗,趁著這個月黑風高的夜晚,就把mongodb的索引總結一番吧。 一,索引介紹 mongodb具有兩類索引,分別為單鍵索引和復合索引。 1.單鍵索引是最簡單的一種索引,創建單鍵索引的開銷要比復合索引
    推薦度:
    標簽: 創建 一些 接觸
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 无码国产乱人伦偷精品视频| 国产精品视频一区二区噜噜| 日韩精品无码一区二区三区免费| 久久国产精品久久久| 亚洲AV无码久久精品成人| 国产欧美日韩精品专区| 国产精品成人免费福利| 无码人妻精品一区二区三区66| 国产免费久久精品丫丫| 国产伦精品一区二区三区女| 无码人妻精品一区二区三区东京热 | 99re8这里有精品热视频免费| 亚洲国产精品VA在线观看麻豆| 99热精品在线观看| 无码人妻丰满熟妇精品区| 婷婷国产成人精品一区二| 国产精品日韩欧美在线第3页| 精品国产sm捆绑最大网免费站| 国产欧美精品区一区二区三区| 国产精品成人在线| 久久久无码人妻精品无码| 欧美日韩精品在线观看| 国产精品秘入口福利姬网站| 久久91精品久久91综合| 精品乱码一区二区三区四区| 中文字幕一精品亚洲无线一区| 久久青青草原精品国产不卡| 国产精品无码不卡一区二区三区| 亚洲综合一区二区国产精品| 国产精品亚洲欧美一区麻豆 | 国产精品亚洲高清一区二区| 久久精品国产免费一区| 99久久国语露脸精品国产| 国产精品一久久香蕉国产线看观看 | 精品无码综合一区| 国产精品自在线拍国产电影| 国产成人精品怡红院在线观看| 91午夜精品亚洲一区二区三区 | 亚洲精品无码精品mV在线观看| 日本精品一区二区久久久| 国产综合成人色产三级高清在线精品发布 |