婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 深入理解MongoDB的復合索引

深入理解MongoDB的復合索引

熱門標簽:怎么投訴地圖標注 廣州長安公司怎樣申請400電話 蘋果汽車租賃店地圖標注 杭州人工電銷機器人價格 濟南電銷機器人加盟公司 電銷機器人是什么軟件 老虎洗衣店地圖標注 云南外呼系統 呼和浩特電銷外呼系統加盟

為什么需要索引?

當你抱怨MongoDB集合查詢效率低的時候,可能你就需要考慮使用索引了,為了方便后續介紹,先科普下MongoDB里的索引機制(同樣適用于其他的數據庫比如mysql)。

mongo-9552:PRIMARYgt; db.person.find()
{ "_id" : ObjectId("571b5da31b0d530a03b3ce82"), "name" : "jack", "age" : 19 }
{ "_id" : ObjectId("571b5dae1b0d530a03b3ce83"), "name" : "rose", "age" : 20 }
{ "_id" : ObjectId("571b5db81b0d530a03b3ce84"), "name" : "jack", "age" : 18 }
{ "_id" : ObjectId("571b5dc21b0d530a03b3ce85"), "name" : "tony", "age" : 21 }
{ "_id" : ObjectId("571b5dc21b0d530a03b3ce86"), "name" : "adam", "age" : 18 }

當你往某各個集合插入多個文檔后,每個文檔在經過底層的存儲引擎持久化后,會有一個位置信息,通過這個位置信息,就能從存儲引擎里讀出該文檔。比如mmapv1引擎里,位置信息是『文件id + 文件內offset 』, 在wiredtiger存儲引擎(一個KV存儲引擎)里,位置信息是wiredtiger在存儲文檔時生成的一個key,通過這個key能訪問到對應的文檔;為方便介紹,統一用pos(position的縮寫)來代表位置信息。

什么是復合索引?

復合索引,即Compound Index,指的是將多個鍵組合到一起創建索引,這樣可以加速匹配多個鍵的查詢。不妨通過一個簡單的示例理解復合索引。

students集合如下:

db.students.find().pretty()
{
 "_id" : ObjectId("5aa7390ca5be7272a99b042a"),
 "name" : "zhang",
 "age" : "15"
}
{
 "_id" : ObjectId("5aa7393ba5be7272a99b042b"),
 "name" : "wang",
 "age" : "15"
}
{
 "_id" : ObjectId("5aa7393ba5be7272a99b042c"),
 "name" : "zhang",
 "age" : "14"
}

在name和age兩個鍵分別創建了索引(_id自帶索引):

db.students.getIndexes()
[
 {
 "v" : 1,
 "key" : {
 "name" : 1
 },
 "name" : "name_1",
 "ns" : "test.students"
 },
 {
 "v" : 1,
 "key" : {
 "age" : 1
 },
 "name" : "age_1",
 "ns" : "test.students"
 }
]

當進行多鍵查詢時,可以通過explian()分析執行情況(結果僅保留winningPlan):

db.students.find({name:"zhang",age:"14"}).explain()
"winningPlan":
{
 "stage": "FETCH",
 "filter":
 {
  "name":
  {
   "$eq": "zhang"
  }
 },
 "inputStage":
 {
  "stage": "IXSCAN",
  "keyPattern":
  {
   "age": 1
  },
  "indexName": "age_1",
  "isMultiKey": false,
  "isUnique": false,
  "isSparse": false,
  "isPartial": false,
  "indexVersion": 1,
  "direction": "forward",
  "indexBounds":
  {
   "age": [
    "[\"14\", \"14\"]"
   ]
  }
 }
}

由winningPlan可知,這個查詢依次分為IXSCAN和FETCH兩個階段。IXSCAN即索引掃描,使用的是age索引;FETCH即根據索引去查詢文檔,查詢的時候需要使用name進行過濾。

為name和age創建復合索引:

db.students.createIndex({name:1,age:1})
db.students.getIndexes()
[
 {
 "v" : 1,
 "key" : {
 "name" : 1,
 "age" : 1
 },
 "name" : "name_1_age_1",
 "ns" : "test.students"
 }
]

有了復合索引之后,同一個查詢的執行方式就不同了:

db.students.find({name:"zhang",age:"14"}).explain()
"winningPlan":
{
 "stage": "FETCH",
 "inputStage":
 {
  "stage": "IXSCAN",
  "keyPattern":
  {
   "name": 1,
   "age": 1
  },
  "indexName": "name_1_age_1",
  "isMultiKey": false,
  "isUnique": false,
  "isSparse": false,
  "isPartial": false,
  "indexVersion": 1,
  "direction": "forward",
  "indexBounds":
  {
   "name": [
    "[\"zhang\", \"zhang\"]"
   ],
   "age": [
    "[\"14\", \"14\"]"
   ]
  }
 }
}

由winningPlan可知,這個查詢的順序沒有變化,依次分為IXSCAN和FETCH兩個階段。但是,IXSCAN使用的是name與age的復合索引;FETCH即根據索引去查詢文檔,不需要過濾。

這個示例的數據量太小,并不能看出什么問題。但是實際上,當數據量很大,IXSCAN返回的索引比較多時,FETCH時進行過濾將非常耗時。接下來將介紹一個真實的案例。

定位MongoDB性能問題

隨著接收的錯誤數據不斷增加,我們Fundebug已經累計處理3.5億錯誤事件,這給我們的服務不斷帶來性能方面的挑戰,尤其對于MongoDB集群來說。

對于生產數據庫,配置profile,可以記錄MongoDB的性能數據。執行以下命令,則所有超過1s的數據庫讀寫操作都會被記錄下來。

db.setProfilingLevel(1,1000)

查詢profile所記錄的數據,會發現events集合的某個查詢非常慢:

db.system.profile.find().pretty()
{
 "op" : "command",
 "ns" : "fundebug.events",
 "command" : {
 "count" : "events",
 "query" : {
 "createAt" : {
 "$lt" : ISODate("2018-02-05T20:30:00.073Z")
 },
 "projectId" : ObjectId("58211791ea2640000c7a3fe6")
 }
 },
 "keyUpdates" : 0,
 "writeConflicts" : 0,
 "numYield" : 1414,
 "locks" : {
 "Global" : {
 "acquireCount" : {
 "r" : NumberLong(2830)
 }
 },
 "Database" : {
 "acquireCount" : {
 "r" : NumberLong(1415)
 }
 },
 "Collection" : {
 "acquireCount" : {
 "r" : NumberLong(1415)
 }
 }
 },
 "responseLength" : 62,
 "protocol" : "op_query",
 "millis" : 28521,
 "execStats" : {
 },
 "ts" : ISODate("2018-03-07T20:30:59.440Z"),
 "client" : "192.168.59.226",
 "allUsers" : [ ],
 "user" : ""
}

events集合中有數億個文檔,因此count操作比較慢也不算太意外。根據profile數據,這個查詢耗時28.5s,時間長得有點離譜。另外,numYield高達1414,這應該就是操作如此之慢的直接原因。根據MongoDB文檔,numYield的含義是這樣的:

The number of times the operation yielded to allow other operations to complete. Typically, operations yield when they need access to data that MongoDB has not yet fully read into memory. This allows other operations that have data in memory to complete while MongoDB reads in data for the yielding operation.

這就意味著大量時間消耗在讀取硬盤上,且讀了非常多次??梢酝茰y,應該是索引的問題導致的。

不妨使用explian()來分析一下這個查詢(僅保留executionStats):

db.events.explain("executionStats").count({"projectId" : ObjectId("58211791ea2640000c7a3fe6"),createAt:{"$lt" : ISODate("2018-02-05T20:30:00.073Z")}})
"executionStats":
{
 "executionSuccess": true,
 "nReturned": 20853,
 "executionTimeMillis": 28055,
 "totalKeysExamined": 28338,
 "totalDocsExamined": 28338,
 "executionStages":
 {
  "stage": "FETCH",
  "filter":
  {
   "createAt":
   {
    "$lt": ISODate("2018-02-05T20:30:00.073Z")
   }
  },
  "nReturned": 20853,
  "executionTimeMillisEstimate": 27815,
  "works": 28339,
  "advanced": 20853,
  "needTime": 7485,
  "needYield": 0,
  "saveState": 1387,
  "restoreState": 1387,
  "isEOF": 1,
  "invalidates": 0,
  "docsExamined": 28338,
  "alreadyHasObj": 0,
  "inputStage":
  {
   "stage": "IXSCAN",
   "nReturned": 28338,
   "executionTimeMillisEstimate": 30,
   "works": 28339,
   "advanced": 28338,
   "needTime": 0,
   "needYield": 0,
   "saveState": 1387,
   "restoreState": 1387,
   "isEOF": 1,
   "invalidates": 0,
   "keyPattern":
   {
    "projectId": 1
   },
   "indexName": "projectId_1",
   "isMultiKey": false,
   "isUnique": false,
   "isSparse": false,
   "isPartial": false,
   "indexVersion": 1,
   "direction": "forward",
   "indexBounds":
   {
    "projectId": [
     "[ObjectId('58211791ea2640000c7a3fe6'), ObjectId('58211791ea2640000c7a3fe6')]"
    ]
   },
   "keysExamined": 28338,
   "dupsTested": 0,
   "dupsDropped": 0,
   "seenInvalidated": 0
  }
 }
}

可知,events集合并沒有為projectId與createAt建立復合索引,因此IXSCAN階段采用的是projectId索引,其nReturned為28338; FETCH階段需要根據createAt進行過濾,其nReturned為20853,過濾掉了7485個文檔;另外,IXSCAN與FETCH階段的executionTimeMillisEstimate分別為30ms和27815ms,因此基本上所有時間都消耗在了FETCH階段,這應該是讀取硬盤導致的。

創建復合索引

沒有為projectId和createAt創建復合索引是個尷尬的錯誤,趕緊補救一下:

db.events.createIndex({projectId:1,createTime:-1},{background: true})

在生產環境構建索引這種事最好是晚上做,這個命令一共花了大概7個小時吧!background設為true,指的是不要阻塞數據庫的其他操作,保證數據庫的可用性。但是,這個命令會一直占用著終端,這時不能使用CTRL + C,否則會終止索引構建過程。

復合索引創建成果之后,前文的查詢就快了很多(僅保留executionStats):

db.javascriptevents.explain("executionStats").count({"projectId" : ObjectId("58211791ea2640000c7a3fe6"),createAt:{"$lt" : ISODate("2018-02-05T20:30:00.073Z")}})
"executionStats":
{
 "executionSuccess": true,
 "nReturned": 0,
 "executionTimeMillis": 47,
 "totalKeysExamined": 20854,
 "totalDocsExamined": 0,
 "executionStages":
 {
  "stage": "COUNT",
  "nReturned": 0,
  "executionTimeMillisEstimate": 50,
  "works": 20854,
  "advanced": 0,
  "needTime": 20853,
  "needYield": 0,
  "saveState": 162,
  "restoreState": 162,
  "isEOF": 1,
  "invalidates": 0,
  "nCounted": 20853,
  "nSkipped": 0,
  "inputStage":
  {
   "stage": "COUNT_SCAN",
   "nReturned": 20853,
   "executionTimeMillisEstimate": 50,
   "works": 20854,
   "advanced": 20853,
   "needTime": 0,
   "needYield": 0,
   "saveState": 162,
   "restoreState": 162,
   "isEOF": 1,
   "invalidates": 0,
   "keysExamined": 20854,
   "keyPattern":
   {
    "projectId": 1,
    "createAt": -1
   },
   "indexName": "projectId_1_createTime_-1",
   "isMultiKey": false,
   "isUnique": false,
   "isSparse": false,
   "isPartial": false,
   "indexVersion": 1
  }
 }
}

可知,count操作使用了projectId和createAt的復合索引,因此非???,只花了46ms,性能提升了將近600倍!??!對比使用復合索引前后的結果,發現totalDocsExamined從28338降到了0,表示使用復合索引之后不再需要去查詢文檔,只需要掃描索引就好了,這樣就不需要去訪問磁盤了,自然快了很多。

參考

  • MongoDB 復合索引
  • MongoDB文檔:Compound Indexes

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

您可能感興趣的文章:
  • MongoDB索引使用詳解
  • MongoDB中唯一索引(Unique)的那些事
  • MongoDB的基礎查詢和索引操作方法總結
  • MongoDB中創建索引需要注意的事項
  • MongoDB性能篇之創建索引,組合索引,唯一索引,刪除索引和explain執行計劃
  • mongodb處理中文索引與查找字符串詳解
  • MongoDB查詢字段沒有創建索引導致的連接超時異常解案例分享
  • 關于MongoDB索引管理-索引的創建、查看、刪除操作詳解
  • MongoDB自動刪除過期數據的方法(TTL索引)
  • 關于對MongoDB索引的一些簡單理解

標簽:廈門 遼陽 雞西 玉林 無錫 興安盟 自貢 泰安

巨人網絡通訊聲明:本文標題《深入理解MongoDB的復合索引》,本文關鍵詞  深入,理解,MongoDB,的,復合,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《深入理解MongoDB的復合索引》相關的同類信息!
  • 本頁收集關于深入理解MongoDB的復合索引的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    高清不卡一区二区在线| 日韩欧美专区在线| 精品国产伦一区二区三区观看方式| 亚洲国产精品成人综合| 亚洲国产精品久久人人爱| 粉嫩av亚洲一区二区图片| 91精品国模一区二区三区| 亚洲三级小视频| 国产一区啦啦啦在线观看| 欧美日韩五月天| 亚洲精品国产精品乱码不99| 国产一区在线精品| 日韩女优视频免费观看| 亚洲综合区在线| 91天堂素人约啪| 国产精品美日韩| 国产成人综合自拍| 久久久久久久av麻豆果冻| 九九国产精品视频| 欧美大肚乱孕交hd孕妇| 视频一区中文字幕| 欧美美女一区二区在线观看| 亚洲一区二区三区在线播放| 色婷婷精品久久二区二区蜜臀av| 国产精品美女久久久久aⅴ| 国产乱子伦一区二区三区国色天香| 欧美群妇大交群中文字幕| 亚洲va国产va欧美va观看| 欧美亚洲高清一区二区三区不卡| 国产精品免费丝袜| 国产iv一区二区三区| 中文字幕精品综合| 99精品黄色片免费大全| 亚洲女同一区二区| 欧美在线一区二区三区| 亚洲综合视频网| 欧美人狂配大交3d怪物一区| 午夜欧美2019年伦理| 日韩视频一区二区三区 | 9191久久久久久久久久久| 亚洲成人在线网站| 91精品国产欧美一区二区18| 免费一级欧美片在线观看| 欧美电影免费观看完整版| 国产精品99久久久久久久女警| 精品国产麻豆免费人成网站| 国产精品自拍在线| 国产精品亲子伦对白| 欧美天天综合网| 奇米精品一区二区三区在线观看| 久久免费视频一区| 粉嫩av一区二区三区粉嫩| 一区二区三区四区精品在线视频| 91超碰这里只有精品国产| 狠狠色综合播放一区二区| 国产精品美女久久久久久久久久久 | 亚洲最新视频在线播放| 欧美日韩欧美一区二区| 国产一区二区h| 亚洲激情第一区| 欧美不卡123| 99re视频精品| 奇米色777欧美一区二区| 日本一二三四高清不卡| 7777精品伊人久久久大香线蕉最新版| 久久精品国产亚洲高清剧情介绍 | 91精品国产aⅴ一区二区| 国产一区二区视频在线| 亚洲欧洲综合另类在线| 日韩欧美国产高清| 日本韩国欧美在线| 国产在线精品一区二区三区不卡| 国产精品久久毛片a| 6080国产精品一区二区| 不卡的av网站| 国产一本一道久久香蕉| 亚洲一区二区三区视频在线播放 | 另类的小说在线视频另类成人小视频在线| 日韩欧美一级在线播放| 日本久久电影网| 国产一区二区不卡老阿姨| 视频一区国产视频| 亚洲乱码中文字幕| 久久久噜噜噜久久中文字幕色伊伊| 色老汉一区二区三区| 成人h精品动漫一区二区三区| 蜜臀久久99精品久久久久宅男| 国产精品成人在线观看| 26uuu亚洲| 日韩三级在线观看| 欧美日韩国产美| 色视频欧美一区二区三区| 国产精品中文有码| 久久99精品一区二区三区 | 久久青草欧美一区二区三区| 欧美做爰猛烈大尺度电影无法无天| 国产成人av福利| 九色|91porny| 激情综合色综合久久综合| 日韩和欧美一区二区三区| 亚洲在线中文字幕| 一区二区免费在线播放| 亚洲欧美国产77777| 亚洲女人****多毛耸耸8| 最近中文字幕一区二区三区| 中文字幕免费观看一区| 国产精品视频一二三| 日本一区二区久久| 亚洲欧美怡红院| 国产精品麻豆久久久| 国产精品视频在线看| 国产精品美女久久久久久2018| 欧美激情综合五月色丁香小说| 久久久亚洲精品一区二区三区| 久久亚洲精品小早川怜子| 久久久久国产精品免费免费搜索| 精品国产91久久久久久久妲己 | 成人午夜视频在线观看| 粉嫩av一区二区三区| 成人高清视频免费观看| 成人一二三区视频| 9色porny自拍视频一区二区| 97久久超碰精品国产| 91福利在线免费观看| 欧美日韩国产小视频在线观看| 欧美精品粉嫩高潮一区二区| 日韩欧美一级二级三级久久久| 精品久久久网站| 中文文精品字幕一区二区| 一色屋精品亚洲香蕉网站| 亚洲精品美腿丝袜| 天天av天天翘天天综合网| 麻豆成人免费电影| 国产成人一区二区精品非洲| av中文一区二区三区| 在线看国产一区二区| 日韩一区二区在线观看视频| 久久久午夜精品理论片中文字幕| 国产亚洲欧美色| 亚洲精选一二三| 麻豆91在线播放| 91偷拍与自偷拍精品| 日韩一区和二区| 国产精品久久久久久亚洲毛片| 亚洲色图在线播放| 美女诱惑一区二区| 91麻豆视频网站| 日韩精品一区二区三区四区视频| 国产精品婷婷午夜在线观看| 亚洲国产另类av| 国产成人av电影在线观看| 在线播放一区二区三区| 国产欧美日韩中文久久| 天天综合网天天综合色| 成人午夜激情视频| 欧美一区二区三区人| 一区视频在线播放| 黄色精品一二区| 欧美中文一区二区三区| 国产偷国产偷精品高清尤物| 亚洲成av人片一区二区| 成人av网站大全| 精品国产91九色蝌蚪| 午夜精品久久久久久久99水蜜桃| 岛国一区二区三区| 欧美电影免费观看高清完整版| 亚洲色图欧洲色图| 成人禁用看黄a在线| 亚洲精品一区二区在线观看| 夜夜操天天操亚洲| 成人激情午夜影院| 日韩美女一区二区三区| 午夜精品影院在线观看| 欧洲一区二区三区在线| 亚洲精品乱码久久久久久黑人| 国产精品一区在线观看乱码 | 日韩美女视频在线| 亚洲国产视频在线| 91麻豆123| 国产精品国产三级国产| 成人综合婷婷国产精品久久 | 一本一道久久a久久精品| 日本一区免费视频| 国产精品一区专区| 久久色成人在线| 国内不卡的二区三区中文字幕| 欧美精品777| 婷婷丁香久久五月婷婷| 欧美性受极品xxxx喷水| 亚洲一区二区在线观看视频 | 亚洲视频你懂的| 成人福利视频网站| 国产精品短视频| av电影在线观看一区| 国产精品的网站| 99久久免费视频.com| 亚洲日本在线天堂| 欧美精品在线观看一区二区| 同产精品九九九| 欧美成人一级视频|