婷婷综合国产,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.

這就意味著大量時間消耗在讀取硬盤上,且讀了非常多次。可以推測,應該是索引的問題導致的。

不妨使用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一免费 | 韩国v欧美v日本v亚洲v| 精品无码三级在线观看视频| 国产精品18久久久| 不卡av在线网| 欧美日韩电影在线| 精品盗摄一区二区三区| 国产精品久久午夜| 一区二区三区影院| 黑人巨大精品欧美一区| 成人国产一区二区三区精品| 成人激情校园春色| 欧美精品久久99久久在免费线| 日韩欧美中文字幕制服| 欧美激情一二三区| 一区二区国产盗摄色噜噜| 日韩高清不卡一区二区三区| 狠狠色丁香九九婷婷综合五月| 91丝袜呻吟高潮美腿白嫩在线观看| 欧美色成人综合| 精品国产乱码久久久久久夜甘婷婷 | 国产一区二区三区电影在线观看| 成人精品小蝌蚪| 欧美日韩一本到| 国产精品久久久久婷婷| 三级一区在线视频先锋| 成人国产电影网| 在线播放国产精品二区一二区四区| 欧美刺激脚交jootjob| 亚洲黄色录像片| 国产传媒日韩欧美成人| 欧美老女人第四色| 国产精品久久福利| 毛片av中文字幕一区二区| 色婷婷国产精品综合在线观看| 制服丝袜在线91| 亚洲欧美日韩国产成人精品影院| 久久精品国产色蜜蜜麻豆| 欧美在线不卡一区| 国产精品入口麻豆原神| 国产一区二区三区香蕉| 欧美日韩电影在线| 亚洲图片欧美色图| 99精品国产热久久91蜜凸| 久久久噜噜噜久久人人看| 日本在线不卡视频| 欧美三级韩国三级日本一级| 国产精品国产三级国产普通话蜜臀 | 国产宾馆实践打屁股91| 日韩欧美不卡在线观看视频| 亚洲1区2区3区视频| 欧洲人成人精品| 亚洲精品免费在线观看| 99精品热视频| 亚洲欧美偷拍卡通变态| 9i看片成人免费高清| 国产精品色在线| caoporn国产精品| 最新欧美精品一区二区三区| 丁香啪啪综合成人亚洲小说| 国产欧美综合在线观看第十页| 亚洲视频资源在线| 久久久www成人免费毛片麻豆| 婷婷亚洲久悠悠色悠在线播放| 色激情天天射综合网| 国产精品电影一区二区三区| 国产成人av福利| 国产欧美日韩麻豆91| 国产一区二区三区在线观看免费 | 国产色产综合产在线视频| 视频一区在线播放| 欧美一区二区视频在线观看| 免费观看在线色综合| 欧美大片一区二区三区| 国内精品久久久久影院色| 久久久午夜电影| 成人av网站在线观看| 亚洲精品一二三区| 欧美肥胖老妇做爰| 国产一区二区精品在线观看| 国产精品剧情在线亚洲| 欧美午夜精品理论片a级按摩| 日本欧美一区二区| 国产欧美精品一区| 色天天综合色天天久久| 青青草国产精品97视觉盛宴 | 欧美日韩成人综合在线一区二区| 亚洲国产欧美日韩另类综合| 日韩视频免费观看高清完整版在线观看 | 中文字幕免费不卡| 在线一区二区三区| 蜜桃av一区二区在线观看| 国产亚洲成av人在线观看导航| 91丨porny丨首页| 久久国产综合精品| 亚洲黄色性网站| 国产天堂亚洲国产碰碰| 在线亚洲欧美专区二区| 国产一区二区在线视频| 伊人婷婷欧美激情| 26uuu久久天堂性欧美| 欧美在线观看视频在线| 国产一区视频在线看| 亚洲综合男人的天堂| 久久久精品欧美丰满| 欧美日韩一区二区三区在线看| 国产成人亚洲综合a∨婷婷图片| 亚洲福利国产精品| 国产精品久久久久久久第一福利 | 亚洲第四色夜色| 欧美国产日韩亚洲一区| 欧美一二三区在线| 欧美三级电影网站| 91论坛在线播放| 成人av第一页| 国产99久久久国产精品潘金网站| 亚洲一区二区三区四区的| 国产精品污污网站在线观看| 精品国产3级a| 538prom精品视频线放| 欧美亚一区二区| 色域天天综合网| 9久草视频在线视频精品| 丰满白嫩尤物一区二区| 国产又粗又猛又爽又黄91精品| 免费观看一级特黄欧美大片| 午夜免费欧美电影| 亚洲线精品一区二区三区 | 欧美一级视频精品观看| 在线观看一区不卡| 色综合天天综合网天天看片| av影院午夜一区| 99re在线视频这里只有精品| 成人av影视在线观看| 波多野结衣亚洲一区| 成人黄色av网站在线| 91原创在线视频| 94-欧美-setu| 91久久香蕉国产日韩欧美9色| 色婷婷亚洲综合| 欧美专区在线观看一区| 欧美丝袜丝交足nylons图片| 欧美日韩精品一区二区天天拍小说| 色综合中文字幕国产| 一本到不卡精品视频在线观看| 91色在线porny| 欧美吞精做爰啪啪高潮| 666欧美在线视频| 欧美videos中文字幕| 久久久午夜精品| 1024国产精品| 丝袜脚交一区二区| 韩国女主播一区| 99久久99久久精品免费看蜜桃| 日本韩国欧美国产| 日韩亚洲国产中文字幕欧美| 精品久久久久久久久久久久包黑料 | 免费人成网站在线观看欧美高清| 久久超级碰视频| 99久久er热在这里只有精品66| 欧美在线影院一区二区| 日韩欧美不卡在线观看视频| 国产日产亚洲精品系列| 亚洲一区二区三区自拍| 韩国一区二区三区| 成人黄色a**站在线观看| 日本道色综合久久| 欧美一二三在线| 亚洲日本在线看| 久久国产成人午夜av影院| 成人晚上爱看视频| 制服丝袜亚洲色图| 国产精品福利av| 日韩avvvv在线播放| 99re这里都是精品| 精品国产乱码久久久久久图片 | 欧美一卡2卡3卡4卡| 国产精品免费人成网站| 无码av免费一区二区三区试看 | 午夜免费久久看| 懂色av噜噜一区二区三区av| 欧美理论在线播放| 中文字幕日韩精品一区| 国内精品写真在线观看| 欧美视频中文一区二区三区在线观看| 亚洲精品一区二区三区在线观看 | 欧美不卡一区二区| 亚洲精品国产第一综合99久久| 韩国av一区二区三区| 91精品国产91久久久久久最新毛片| 国产精品福利在线播放|