欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品

主頁 > 知識庫 > 深入理解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的復合索引的相關信息資訊供網民參考!
  • 推薦文章
    欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品
  • <rt id="w000q"><acronym id="w000q"></acronym></rt>
  • <abbr id="w000q"></abbr>
    <rt id="w000q"></rt>
    91麻豆精品久久毛片一级| 久久精品视频在线看| 一区二区三区高清| av午夜精品一区二区三区| 中文字幕五月天| 国产精品久久久久久福利一牛影视| 国产精品99久久久久| 国产美女网站视频| 国产精品网站在线观看| 成人性生交大片免费看视频在线| 欧美a级片免费看| 中文字幕 久热精品 视频在线| 国产精品一区二区91| 青青青视频在线播放| 久久精品视频免费观看| 国产精品综合av一区二区国产馆| 亚洲精品成人av久久| 国产亚洲精久久久久久| 国产精品系列在线观看| 熟女av一区二区| 亚洲少妇最新在线视频| 免费人成视频在线播放| 欧美日韩一区二区三区不卡| 亚洲成人av中文| 亚洲天堂资源在线| 精品播放一区二区| 成人一级视频在线观看| 在线免费观看成人短视频| 亚洲一区二区三区四区的| 69亚洲乱人伦| wwwwxxxx国产| 久久这里只有精品首页| 国产成人自拍网| 色狠狠色狠狠综合| 天堂av在线一区| 亚洲久久久久久久| 国产精品色在线| 91一区二区三区在线观看| 欧美日韩国产另类一区| 免费观看日韩av| 成人黄色短视频| 一区二区三区成人| 蜜桃传媒一区二区亚洲av| 久久久蜜桃精品| aaa亚洲精品| 91精品国产综合久久精品图片 | 欧美成人欧美edvon| 国产在线视频一区二区三区| 日本老熟俱乐部h0930| 亚洲一二三级电影| 成人激情五月天| 亚洲欧美自拍偷拍| 福利电影一区二区三区| 欧美特级限制片免费在线观看| 日本少妇一区二区| 欧美做受xxxxxⅹ性视频| 国产精品视频九色porn| 妖精视频一区二区| 国产欧美一区二区精品性色| 国产成人av免费观看| 2欧美一区二区三区在线观看视频| 成人激情图片网| 欧美大片一区二区三区| 不卡免费追剧大全电视剧网站| 91精品婷婷国产综合久久性色| 国产九色精品成人porny| 欧美日韩国产美| 国产成人免费视频网站| 制服丝袜国产精品| 成人性生交大片免费看中文网站| 7777精品伊人久久久大香线蕉 | 91麻豆精品在线观看| 日韩免费高清av| 99精品视频一区二区三区| 欧美成人一级视频| 杨幂一区二区国产精品| 国产午夜精品久久久久久免费视| 亚洲美女高潮久久久| 国产精品欧美一区二区三区| 风间由美一二三区av片| 18涩涩午夜精品.www| 韩国女同性做爰三级| 全程偷拍露脸中年夫妇| 男女性色大片免费观看一区二区| 色乱码一区二区三区88| 狠狠色狠狠色综合系列| 69堂国产成人免费视频| av成人免费在线| 欧美激情在线免费观看| 日韩精品卡通动漫网站| 一区二区三区中文字幕| 日本黄色片免费观看| 精品一区二区三区久久| 欧美精品自拍偷拍动漫精品| www.欧美色图| 国产欧美一区二区精品久导航| 特级西西人体wwwww| 亚洲国产综合在线| 好吊色视频在线观看| 国产精品资源在线| 欧美成人性战久久| 国产真实乱人偷精品| 一区二区三区四区高清精品免费观看 | 亚洲综合网在线观看| 亚洲aⅴ怡春院| 欧美性色aⅴ视频一区日韩精品| 高清shemale亚洲人妖| 精品国产免费久久 | 日韩精品专区在线影院重磅| 熟女人妻一区二区三区免费看 | 很污很黄的网站| 日本女优在线视频一区二区| 欧美日韩久久不卡| 丰满人妻一区二区三区53视频| 中文字幕一区二区三区四区 | 亚洲色成人网站www永久四虎 | 久久久综合视频| 免费毛片视频网站| 蜜臀a∨国产成人精品| 日韩一区二区精品葵司在线| 国产婷婷在线观看| 午夜精品123| 5858s免费视频成人| 毛茸茸free性熟hd| 午夜精品123| 日韩一级在线观看| 香蕉视频黄色在线观看| 日韩av电影免费观看高清完整版在线观看 | 国产日产精品一区| 国产一二三四视频| 国产成人免费在线观看不卡| 国产精品色噜噜| 极品久久久久久| 91无套直看片红桃| 夜夜嗨av一区二区三区网页 | 成人黄色av网站在线| 一区视频在线播放| 91黄视频在线| 伊人久久久久久久久| 五月综合激情婷婷六月色窝| 欧美一区二区三区思思人| 欧美 变态 另类 人妖| 久久精品99久久久| 国产精品婷婷午夜在线观看| 亚洲色图综合区| 中文字幕人妻无码系列第三区| 亚洲一二三级电影| 日韩欧美国产三级| 国产精品18在线| thepron国产精品| 亚洲高清免费观看高清完整版在线观看 | 欧美亚洲禁片免费| 亚洲久久久久久| 国产在线视频一区二区三区| 国产精品伦理一区二区| 欧美性猛片aaaaaaa做受| 小毛片在线观看| 激情久久久久久久久久久久久久久久| 国产清纯美女被跳蛋高潮一区二区久久w| 国产激情无码一区二区三区| 91浏览器打开| 免费成人在线观看视频| 国产日韩欧美综合在线| 色天使色偷偷av一区二区| 尤物网站在线观看| 国产一区二区三区四区五区美女| 亚洲欧洲三级电影| 91精品国产综合久久小美女| 天天操天天干天天操天天干| 成人国产精品免费| 婷婷中文字幕综合| 国产日本亚洲高清| 欧美日韩一区二区三区四区| 无码国产69精品久久久久同性| 成人免费视频一区| 日韩二区在线观看| 国产精品超碰97尤物18| 91精品国产入口在线| 欧美做爰啪啪xxxⅹ性| 催眠调教后宫乱淫校园| 韩国av一区二区三区| 一区二区三区波多野结衣在线观看| 日韩美女一区二区三区四区| 欧产日产国产v| 久久精品综合视频| 99久久婷婷国产精品综合| 日韩精品91亚洲二区在线观看| 欧美日韩一区三区| 超碰人人干人人| 日本精品一二三| 国产成人免费av在线| 丝袜亚洲另类丝袜在线| 国产精品电影一区二区三区| 欧美一级二级三级乱码| 一本大道久久a久久综合婷婷 | 久久久久久久久一| 欧美日韩一区二区在线视频| 黄色激情小视频| 日本一区二区三区网站| 91在线小视频|