欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MongoDB慢查詢與索引實(shí)例詳解

 更新時(shí)間:2022年07月29日 09:39:17   作者:女友在高考  
索引通常能夠極大的提高查詢的效率,這篇文章主要給大家介紹了關(guān)于MongoDB慢查詢與索引的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

MongoDB慢查詢

慢查詢分析

  • 開(kāi)啟內(nèi)置的慢查詢分析器
db.setProfilingLevel(n,m),n的取值可選0,1,2
  • 0:表示不記錄
  • 1:表示記錄慢速操作,如果值為1,m需要傳慢查詢的閾值,單位為ms
  • 2:表示記錄所有的讀寫(xiě)操作

示例:

db.setProfilingLevel(1,3)
  • 查詢監(jiān)控結(jié)果
db.system.profile.find().sort({millis:-1}).limit(3)

MongoDB索引

什么是索引?

索引是一種單獨(dú)的、物理的對(duì)數(shù)據(jù)庫(kù)表中一列或多列的值進(jìn)行排序的一種存儲(chǔ)結(jié)構(gòu),它是某個(gè)表中一列或若干列值的集合和相應(yīng)的指向表中物理標(biāo)識(shí)這些值的數(shù)據(jù)頁(yè)的邏輯指針清單。索引的作用相當(dāng)于圖書(shū)的目錄,可以根據(jù)目錄中的頁(yè)碼快速找到所需的內(nèi)容。索引目標(biāo)是提高數(shù)據(jù)庫(kù)的查詢效率,沒(méi)有索引的話,查詢會(huì)進(jìn)行全表掃描(scaneverydocumentinacollection),數(shù)據(jù)量大時(shí)嚴(yán)重降低了查詢效率。默認(rèn)情況下Mongo在一個(gè)集合(collection)創(chuàng)建時(shí),自動(dòng)地對(duì)集合的_id創(chuàng)建了唯一索引。

索引結(jié)構(gòu)

MongoDB的索引結(jié)構(gòu)為B樹(shù)

B樹(shù)非葉子節(jié)點(diǎn)也存了數(shù)據(jù),查詢效率不固定,最好的情況是O(1),在單次查詢的情況下平均性能是優(yōu)于B+樹(shù)的。而MongoDB是被作為一個(gè)單一查詢比較多,遍歷數(shù)據(jù)比較少的一個(gè)定位。所以采用了B樹(shù)。

那為什么不用單次性能更好的Hash結(jié)構(gòu)呢?

因?yàn)殡m然遍歷數(shù)據(jù)的情況較少,但是對(duì)于遍歷數(shù)據(jù)也需要有相對(duì)較好的性能支持。Hash這種性能表現(xiàn)較為極端的數(shù)據(jù)結(jié)構(gòu)往往只能在簡(jiǎn)單、極端的場(chǎng)景下使用。

索引分類

  • 單鍵索引

MongoDB支持所有數(shù)據(jù)類型中的單個(gè)字段索引,并且可以在文檔的任何字段定義。對(duì)于單個(gè)字段索引,索引鍵的排序順序無(wú)關(guān)緊要,因?yàn)镸ongoDB可以在任一方向讀取索引。

db.集合名.createIndex({"字段名":排序方式})

示例:

db.user.createIndex({"name":1})

創(chuàng)建后可以通過(guò)查詢索引命令查看是否創(chuàng)建成功。

db.user.getIndexes()
  • 唯一索引

設(shè)置unique為true。示例:

db.book.createIndex({title:1},{unique:true})
  • 過(guò)期索引TTL

TTL索引是MongoDB中一種特殊的索引,可以支持文檔在一定時(shí)間之后自動(dòng)過(guò)期刪除,目前TTL索引只能在單字段上建立,并且字段類型必須是日期類型。

db.集合名.createIndex({"日期字段":排序方式}, {expireAfterSeconds: 秒數(shù)})

示例:

db.user.createIndex({"bithday":1}, {expireAfterSeconds: 10})

創(chuàng)建過(guò)期索引后,有bithday字段的文檔會(huì)在約10秒后自動(dòng)刪除。

  • 復(fù)合索引

通常我們需要在多個(gè)字段上進(jìn)行搜索,如果是這種情況,可以考慮使用復(fù)合索引。復(fù)合索引支持基于多個(gè)字段的索引,這擴(kuò)展了索引的概念并將它們擴(kuò)展到索引中的更大域。

建立復(fù)合索引需要注意:字段順序和索引方向。它也是遵循最左前綴原則。

db.集合名.createIndex( { "字段名1" : 排序方式, "字段名2" : 排序方式 } )
  • 多鍵索引

針對(duì)屬性包含數(shù)組數(shù)據(jù)的情況,MongoDB支持針對(duì)數(shù)組中每一個(gè)element創(chuàng)建索引,支持Strings、numbers、nested documents。

示例:

//type是集合類型的數(shù)據(jù),創(chuàng)建的就是多鍵索引
db.book.insert({title:"java",type:["技術(shù)","IT"]})

db.book.createIndex({type:1})
  • 哈希索引

針對(duì)屬性的哈希值進(jìn)行索引查詢,當(dāng)要使用Hashed Index時(shí),MongoDB能夠自動(dòng)計(jì)算hash值來(lái)進(jìn)行查詢。

db.集合.createIndex({"字段": "hashed"})
  • 地理空間索引

針對(duì)地理空間坐標(biāo)數(shù)據(jù)創(chuàng)建索引。2dsphere索引:用于存儲(chǔ)和查找球面上的點(diǎn)。

2d索引:用于存儲(chǔ)和查找平面上的點(diǎn)。

db.集合名.ensureIndex({字段名:"2dsphere"})

示例:

//插入數(shù)據(jù)
db.company.insert({
    loc:{type:"Point",coordinates:[116.482451,39.914176]},
    name:"大望路",
    category:"Parks"
})

//創(chuàng)建索引
db.company.ensureIndex({loc:"2dsphere"})

//查詢范圍內(nèi)的數(shù)據(jù)
db.company.find({
    "loc":{
    "$geoWithin":{
        "$center":[[116.482450,39.914176],0.05]
    }
}
})

//距離指定位置最近的2個(gè)點(diǎn)
db.company.aggregate([
    {
        $geoNear: {
          near: {
              type: "Point",
              coordinates: [ 116.472451,39.814176]
          },
          key:"loc",
          distanceField: "dist.calculated",
          spherical: true
        }
    },
    {
        $limit: 2
    }
    ])

索引管理

  • 創(chuàng)建索引并在后臺(tái)運(yùn)行

有時(shí)數(shù)據(jù)量大的時(shí)候,創(chuàng)建索引的動(dòng)作是比較耗費(fèi)時(shí)間的,這時(shí)后臺(tái)運(yùn)行就比較有用了。

db.COLLECTION_NAME.createIndex({"字段":排序方式}, {background: true});
  • 查詢某個(gè)集合的索引
db.COLLECTION_NAME.getIndexes()
  • 查看索引大小
db.COLLECTION_NAME.totalIndexSize()
  • 索引重建
db.COLLECTION_NAME.reIndex()
  • 索引刪除
db.COLLECTION_NAME.dropIndex("INDEX-NAME")
db.COLLECTION_NAME.dropIndexes()
注意: _id 對(duì)應(yīng)的索引是刪除不了的

Explain分析

explain()是一個(gè)查詢分析的方法,它還可以接收不同的參數(shù)來(lái)查看更詳細(xì)的查詢計(jì)劃。

簡(jiǎn)單示例:

db.user.find().explain()
db.user.find({name:"test1"}).explain("executionStats")

參數(shù)介紹:

  • queryPlanner:queryPlanner是默認(rèn)參數(shù),具體執(zhí)行計(jì)劃信息參考下面的表格
  • executionStats:executionStats會(huì)返回執(zhí)行計(jì)劃的一些統(tǒng)計(jì)信息(有些版本中和allPlansExecution等同)。
  • allPlansExecution:allPlansExecution用來(lái)獲取所有執(zhí)行計(jì)劃,結(jié)果參數(shù)基本與上文相同
  • queryPlanner參數(shù)查詢返回值含義
參數(shù)含義
plannerVersion查詢計(jì)劃版本
namespace要查詢的集合(該值返回的是該query所查詢的表)數(shù)據(jù)庫(kù).集合
indexFilterSet針對(duì)該query是否有indexFilter
parsedQuery查詢條件
winningPlan被選中的執(zhí)行計(jì)劃
winningPlan.stage被選中執(zhí)行計(jì)劃的stage(查詢方式),常見(jiàn)的有:COLLSCAN/全表掃描:(應(yīng)該知道就是CollectionScan,就是所謂的“集合掃描”,和mysql中tablescan/heapscan類似,這個(gè)就是所謂的性能最爛最無(wú)奈的由來(lái))、IXSCAN/索引掃描:(是IndexScan,這就說(shuō)明我們已經(jīng)命中索引了)、FETCH/根據(jù)索引去檢索文檔、SHARD_MERGE/合并分片結(jié)果、IDHACK/針對(duì)_id進(jìn)行查詢等
winningPlan.inputStage用來(lái)描述子stage,并且為其父stage提供文檔和索引關(guān)鍵字。
winningPlan.stage的child stage如果此處是IXSCAN,表示進(jìn)行的是index scanning。
winningPlan.keyPattern所掃描的index內(nèi)容
winningPlan.indexNamewinning plan所選用的index。
winningPlan.isMultiKey是否是Multikey,此處返回是false,如果索引建立在array上,此處將是true。
winningPlan.direction此query的查詢順序,此處是forward,如果用了.sort({字段:-1})將顯示backward。
filter過(guò)濾條件
winningPlan.indexBoundswinningplan所掃描的索引范圍,如果沒(méi)有制定范圍就是[MaxKey,MinKey],這主要是直接定位到mongodb的chunck中去查找數(shù)據(jù),加快數(shù)據(jù)讀取。
rejectedPlans被拒絕的執(zhí)行計(jì)劃的詳細(xì)返回,其中具體信息與winningPlan的返回中意義相同,故不在此贅述
serverInfoMongoDB服務(wù)器信息
  • executionStats參數(shù)查詢返回值含義
參數(shù)含義
executionSuccess是否執(zhí)行成功
nReturned返回的文檔數(shù)
executionTimeMillis執(zhí)行耗時(shí)
totalKeysExamined索引掃描次數(shù)
totalDocsExamined文檔掃描次數(shù)
executionStages這個(gè)分類下描述執(zhí)行的狀態(tài)
stage掃描方式,具體可選值與上文的相同
nReturned查詢結(jié)果數(shù)量
executionTimeMillisEstimate檢索document獲得數(shù)據(jù)的時(shí)間
inputStage.executionTimeMillisEstimate該查詢掃描文檔 index所用時(shí)間
works工作單元數(shù),一個(gè)查詢會(huì)分解成小的工作單元
advanced優(yōu)先返回的結(jié)果數(shù)
docsExamined文檔檢查數(shù)目,與totalDocsExamined一致。檢查了總共的document個(gè)數(shù),而從返回上面的nReturned數(shù)量

這么多返回值我們?cè)趺捶治瞿兀?/p>

首先我們先造點(diǎn)數(shù)據(jù):

for(var i=0;i<100000;i++){
    db.user.insert({
        name:"test"+i,
        explectSalary:10+i
    })
}

查詢耗時(shí)115

db.user.find({name:'test1'}).explain("allPlansExecution")

然后創(chuàng)建索引

db.user.createIndex({name:1})

再次查詢,查看耗時(shí)變?yōu)榱?。速度直線飆升。我們?cè)賹?duì)返回結(jié)果做一個(gè)分析:

{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "test.user",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "name" : {
                                "$eq" : "test1"
                        }
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "name" : 1
                                },
                                "indexName" : "name_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "name" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "name" : [
                                                "[\"test1\", \"test1\"]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 2,
                "executionTimeMillis" : 2,
                "totalKeysExamined" : 2,
                "totalDocsExamined" : 2,
                "executionStages" : {
                        "stage" : "FETCH",
                        "nReturned" : 2,
                        "executionTimeMillisEstimate" : 0,
                        "works" : 3,
                        "advanced" : 2,
                        "needTime" : 0,
                        "needYield" : 0,
                        "saveState" : 0,
                        "restoreState" : 0,
                        "isEOF" : 1,
                        "docsExamined" : 2,
                        "alreadyHasObj" : 0,
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "nReturned" : 2,
                                "executionTimeMillisEstimate" : 0,
                                "works" : 3,
                                "advanced" : 2,
                                "needTime" : 0,
                                "needYield" : 0,
                                "saveState" : 0,
                                "restoreState" : 0,
                                "isEOF" : 1,
                                "keyPattern" : {
                                        "name" : 1
                                },
                                "indexName" : "name_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "name" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "name" : [
                                                "[\"test1\", \"test1\"]"
                                        ]
                                },
                                "keysExamined" : 2,
                                "seeks" : 1,
                                "dupsTested" : 0,
                                "dupsDropped" : 0
                        }
                },
                "allPlansExecution" : [ ]
        },
        "serverInfo" : {
                "host" : "10.0.3.15",
                "port" : 27017,
                "version" : "4.2.21",
                "gitVersion" : "b0aeed9445ff41af07449fa757e1f231bce990b3"
        },
        "ok" : 1
}

折疊

重要參數(shù)介紹:

  • executionStats.executionTimeMillis 整體查詢時(shí)間
  • executionStats.executionStages.executionTimeMillisEstimate 該查詢檢索document獲得數(shù)據(jù)的時(shí)間
  • executionStats.inputStage.executionTimeMillisEstimate 該查詢掃描文檔index所用的時(shí)間
  • executionStats.nReturned 查詢返回的條數(shù)
  • executionStats.totalKeysExamined:索引掃描條數(shù)
  • executionStats.totalDocsExamined:文檔掃描條數(shù)

對(duì)于一個(gè)查詢,我們最理想的狀態(tài)是:nReturned=totalKeysExamined=totalDocsExamined

  • stage狀態(tài):它的值有很多,如下所示:

類型列舉如下:

  • COLLSCAN:全表掃描
  • IXSCAN:索引掃描
  • FETCH:根據(jù)索引去檢索指定document
  • SHARD_MERGE:將各個(gè)分片返回?cái)?shù)據(jù)進(jìn)行merge
  • SORT:表明在內(nèi)存中進(jìn)行了排序
  • LIMIT:使用limit限制返回?cái)?shù)
  • SKIP:使用skip進(jìn)行跳過(guò)
  • IDHACK:針對(duì)_id進(jìn)行查詢
  • SHARDING_FILTER:通過(guò)mongos對(duì)分片數(shù)據(jù)進(jìn)行查詢
  • COUNT:利用db.coll.explain().count()之類進(jìn)行count運(yùn)算
  • TEXT:使用全文索引進(jìn)行查詢時(shí)候的stage返回
  • PROJECTION:限定返回字段時(shí)候stage的返回

還有的是上面的組合

  • Fetch+IDHACK
  • Fetch+IXSCAN
  • Limit+(Fetch+IXSCAN)
  • PROJECTION+IXSCAN
  • SHARDING_FITER+IXSCAN

總結(jié) 

到此這篇關(guān)于MongoDB慢查詢與索引的文章就介紹到這了,更多相關(guān)MongoDB慢查詢與索引內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mongodb 常見(jiàn)問(wèn)題處理方法收集

    mongodb 常見(jiàn)問(wèn)題處理方法收集

    這篇文章主要介紹了mongodb 常見(jiàn)問(wèn)題收集,這里的問(wèn)題是我在看MongoDB官網(wǎng)文章時(shí),從里面總結(jié)出來(lái)的,需要的朋友可以參考下
    2017-03-03
  • MongoDB的基礎(chǔ)知識(shí)簡(jiǎn)介

    MongoDB的基礎(chǔ)知識(shí)簡(jiǎn)介

    這篇文章主要介紹了MongoDB的基礎(chǔ)知識(shí)簡(jiǎn)介,需要的朋友可以參考下
    2017-05-05
  • MongoDB日志文件過(guò)大的解決方法

    MongoDB日志文件過(guò)大的解決方法

    這篇文章主要介紹了MongoDB日志文件過(guò)大的解決方法,本文給出了一種不需要重啟MongoDB服務(wù)的方法重新開(kāi)啟一個(gè)新日志文件,需要的朋友可以參考下
    2014-10-10
  • mongodb使用心得簡(jiǎn)單總結(jié)

    mongodb使用心得簡(jiǎn)單總結(jié)

    本文整理了一年多以來(lái)我常用的MongoDB操作,既有運(yùn)維層面也有應(yīng)用層面,內(nèi)容有淺有深,這也就是我從零到熟練的歷程。
    2016-01-01
  • MongoDB查詢操作限制返回字段的方法

    MongoDB查詢操作限制返回字段的方法

    這篇文章主要介紹了MongoDB查詢操作限制返回字段的方法,需要的朋友可以參考下
    2014-05-05
  • Centos 7.2中MongoDB數(shù)據(jù)庫(kù)的安裝與卸載教程

    Centos 7.2中MongoDB數(shù)據(jù)庫(kù)的安裝與卸載教程

    這篇文章主要給大家介紹了關(guān)于在Centos 7.2中MongoDB數(shù)據(jù)庫(kù)的安裝與卸載的相關(guān)資料,文中還給大家總結(jié)了在過(guò)程中可能會(huì)遇到的一些問(wèn)題的解決方法,需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • MongoDB開(kāi)啟權(quán)限認(rèn)證的方法步驟詳解

    MongoDB開(kāi)啟權(quán)限認(rèn)證的方法步驟詳解

    MongoDB已經(jīng)使用很長(zhǎng)一段時(shí)間了,基于MongoDB的數(shù)據(jù)存儲(chǔ)也一直沒(méi)有使用到權(quán)限訪問(wèn)(MongoDB默認(rèn)設(shè)置為無(wú)權(quán)限訪問(wèn)限制),最近深入學(xué)習(xí)了下,所以下面這篇文章主要給大家介紹了關(guān)于MongoDB開(kāi)啟權(quán)限認(rèn)證的相關(guān)資料,需要的朋友可以參考下。
    2018-02-02
  • MongoDB 數(shù)據(jù)庫(kù)的命名、設(shè)計(jì)規(guī)范詳解

    MongoDB 數(shù)據(jù)庫(kù)的命名、設(shè)計(jì)規(guī)范詳解

    隨著MongoDB的普及和使用量的快速增長(zhǎng),為了規(guī)范使用,便于管理和獲取更高的性能,整理此文檔
    2020-02-02
  • MongoDB模糊查詢操作案例詳解(類關(guān)系型數(shù)據(jù)庫(kù)的 like 和 not like)

    MongoDB模糊查詢操作案例詳解(類關(guān)系型數(shù)據(jù)庫(kù)的 like 和 not like)

    這篇文章主要介紹了MongoDB的模糊查詢操作(類關(guān)系型數(shù)據(jù)庫(kù)的 like 和 not like) ,本文通過(guò)代碼案例分析給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,,需要的朋友可以參考下
    2019-07-07
  • MongoDB的chunk詳解

    MongoDB的chunk詳解

    這篇文章主要介紹了MongoDB的chunk的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用MongoDB數(shù)據(jù)庫(kù),感興趣的朋友可以了解下
    2021-04-04

最新評(píng)論