【資料庫寶典】 MongoDB - 進階索引

更新於 發佈於 閱讀時間約 12 分鐘

MongoDB - 索引類型

本篇主要是介紹MongoDB有哪些進階的索引, 了解原理及功能後, 在應用上才能規劃出更有效率的索引, 而主要會談到以下五個索引類型:

  • 複合索引。
  • 部份索引。
  • 多鍵索引。
  • 全文索引。
  • TTL索引。

進入到索引類型之前先提醒一下,一個集合的索引數不能超過64個。

複合索引

raw-image

限制: 最多只能31個欄位做一組複合索引。

建立方式:

db.collection.createIndex( { <field1>: <type>, <field2>: <type2>, ... } )
// 補充: <type>就是1或-1,代表正序或倒序。

首先我們實際來建立一組索引,叫做「人員分數查詢」專用的索引。

db.collection.createIndex({ userid: 1, score: -1}, {name: "人員分數查詢專用索引"})

接著建立幾個樣本資料:

[
{
"userid": "aa1",
"score": 45
},
{
"userid": "ca2",
"score": 55
},
{
"userid": "ca2",
"score": 75
},
{
"userid": "ca2",
"score": 30
},
{
"userid": "nb1",
"score": 30
},
{
"userid": "xyz",
"score": 90
}
]

案例一: 查詢條件發揮複合索引效用。

接著我們來做個查詢分析,分析我們的條件是否在索引之下發揮最大效用。

db.getCollection('test').find({"userid": "ca2", "score": 30}).explain("executionStats")

我們可以發現到Mongo選出來的最佳查詢計畫stage是FETCH,這個我們可以理解為透過索引直接找到文本,而inputStage代表著我們先針對userid, score這兩個索引做掃描,關於查詢分析這邊先不探討,會另外開一篇專門介紹。

  • COLLSCAN:全表掃描。
  • IXSCAN:索引掃描。
  • FETCH: 根據索引到指定的document。
raw-image

上述結果成功發揮索引效用。

案例二: 查詢條件未能發揮效用

假設今天只找分數不找人員

db.getCollection('test').find({"score": 30}).explain("executionStats")
raw-image

我們可以發現到Mongo分析出來的查詢計畫是全局掃描,也就是未能發揮索引效用,因此索引建立的順序是有意義的,需要根據需求來進行索引設計。

適用場景: 查詢欄位不只一個,且複合索引的欄位符合建立索引的順序,才能發揮最大的效用*。*

部分索引

raw-image

我們不想針對該欄位全部的value都進行索引,就可以使用這種索引方式,舉例來說,我們只想對age > 25的值進行索引,建立方式如下:

db.persons.createIndex({country:1},{partialFilterExpression: {age: {$gt:25}}})
  • 其實就是帶有過濾條件的索引,大數據的應用確實應該分析及規劃這個部分。
  • 滿足查詢條件在查詢時才能發揮索引效用,假設我們條件改為age >= 25,那麼Mongo的查詢計畫就會給出全局掃描的選項。

多鍵索引

raw-image

其實就是對嵌套的文檔做索引。

全文索引

  • 目前不支援中文。
  • 會以空白隔開的方式來建立索引。
{
"id": "1",
"post_text": "enjoy the mongodb articles on Runoob",
}db.posts.ensureIndex({post_text:"text"})# 索引示意: 會以term做為索引的key來記載出現的位置...。
# enjoy => [1, 2...]
# the => [1...]
# ...
  • 搜尋也是有一些強大功能的, 如下:
// 簡單的查詢mongodb這個詞。
db.posts.find( { $text: { $search: "mongodb" } } );
// 查詢mongodb或articles這兩個詞。
db.posts.find({$text:{$search:"mongodb articles"}});
// 查詢包含mongodb但不包含elasticsearch的文本, 會用`-`來表示不包含。
db.posts.find({$text:{$search:"mongodb -elasticsearch"}});
// 查詢「mongodb articles」這個片語的文本。
db.posts.find({$text:{$search:"\\"mongodb articles\\""}})

TTL索引

TTL索引常常用在log應用, 假設使用者操作的歷程我們只想要保留半年, 則我們可以針對Collection進行TTL索引的建立, 而Mongo背景服務就會定時幫我們清除過期的資料, 但是使用上有幾個特別要注意的地方如下:

清除的型態是什麼?

  • 只能是BSON的Date型態才能被清除。
  • 如果用整數的Timestamp會沒有作用。

如果Collection本身已經是Capped的話, 我們又設定TTL會發生什麼事情呢?

會發生以下的錯誤訊息, 由於我們基礎篇有提到Capped Collection如果要刪除Document只能對整個Collection進行刪除, 故我們如果需求上已經對某個Collection規劃為Capped時, 就不要在用TTL索引了!!!

2020-11-23T03:36:21.405+0000 E INDEX    [TTLMonitor] Error processing ttl index: { v: 2, key: { creationTime: 1 }, name: "expiredIdx", ns: "qa.qm_event_log", expireAfterSeconds: 1, background: true } -- 10089 cannot remove from a capped collection

如何更新TTL失效時間?

  • 已建立的索引, 如果動態更改TTL參數會發生錯誤如下。
db.createIndex(...)
Index with name: expiredIdx already exists with different options
  • 使用DB Command「collMod」來更新。
// Update the index with 120 seconds expiration threshold
db.runCommand({
collMod: 'ttldemo',
index: {keyPattern: {created_at: 1}, expireAfterSeconds: 120}
});
  • 刪除重建。

刪除重建後,之前的Documents會套用嗎?

  • 我們先預設一小時後失效。
db.test.createIndex({created_at: 1}, {expireAfterSeconds: 600});
  • 建立一筆Document時間為now。
db.test.insert({
created_at: new Date()
})
  • 此時我們先確保背景服務不會去刪除我們的Document
2020-11-23T04:22:21.437+0000 D INDEX    [TTLMonitor] ns: qa.test key: { created_at: 1.0 } name: created_at_1
2020-11-23T04:22:21.437+0000 D INDEX [TTLMonitor] deleted: 0
  • 刪除重建索引為1秒鐘後失效。
db.test.dropIndex("created_at_1");
db.test.createIndex({created_at: 1}, {expireAfterSeconds: 1});
  • 再建立一筆Document時間為now。
db.test.insert({
created_at: new Date()
})
  • 此時已有兩筆, 我們來看看是否兩筆都會套用? 答案是會的!
2020-11-23T04:25:21.439+0000 D INDEX    [TTLMonitor] ns: qa.test key: { created_at: 1.0 } name: created_at_1
2020-11-23T04:25:21.439+0000 D INDEX [TTLMonitor] deleted: 2

如何監控TTL是否執行?

預設的MongoDB不會將TTL訊息印出, 如果我們打算讓該Log訊息印出, 則可以透過以下的配置來完成。

db.setLogLevel(1, "index");

印出訊息如下, Log會告知我們哪個時間點清除了哪些資料:

2020-11-23T03:40:21.407+0000 D INDEX    [TTLMonitor] ns: admin.logsfilter key: { expiredAt: 1 } name: expiredAt_1
2020-11-23T03:40:21.407+0000 D INDEX [TTLMonitor] deleted: 0
2020-11-23T03:40:21.407+0000 D INDEX [TTLMonitor] ns: qa.error_log key: { creationTime: 1 } name: expiredIdx
2020-11-23T03:40:21.407+0000 D INDEX [TTLMonitor] deleted: 0

MongoDB背景多久執行一次TTL清除動作?

  • 預設60秒執行一次清除動作。
db.adminCommand({getParameter:1, ttlMonitorSleepSecs: 1});{
"ttlMonitorSleepSecs" : 60,
"ok" : 1.0
}
  • 如何更改執行間隔(盡量不要太短, TTL索引過多將造成CPU負荷)。
> db.adminCommand({setParameter:1, ttlMonitorSleepSecs: 3600}); // 1 minute
{ "was" : 60, "ok" : 1 }

TTL刪除了多少Document

db.serverStatus().metrics.ttl
{
"deletedDocuments" : NumberLong(13533),
"passes" : NumberLong(20374)
}

常用的指令

# 查看collection佔用索引的容量
db.collection.totalIndexSize()
留言
avatar-img
留言分享你的想法!
avatar-img
阿Han的沙龍
129會員
285內容數
哈囉,我是阿Han,是一位 👩‍💻 軟體研發工程師,喜歡閱讀、學習、撰寫文章及教學,擅長以圖代文,化繁為簡,除了幫助自己釐清思路之外,也希望藉由圖解的方式幫助大家共同學習,甚至手把手帶您設計出高品質的軟體產品。
阿Han的沙龍的其他內容
2023/08/08
我們在「【資料庫寶典】什麼是NoSQL?能吃嗎?」有談到一些NoSQL的特性,雖然本質上有所差異,但兩方技術發展的產品也都開始互相支援了,比如說MongoDB後來也發展出類SQL語法讓熟悉SQL的開發者可以降低進入門檻,而SQL、postgresql…等也紛紛納入一些NoSQL的元素,雙方都有開始接
Thumbnail
2023/08/08
我們在「【資料庫寶典】什麼是NoSQL?能吃嗎?」有談到一些NoSQL的特性,雖然本質上有所差異,但兩方技術發展的產品也都開始互相支援了,比如說MongoDB後來也發展出類SQL語法讓熟悉SQL的開發者可以降低進入門檻,而SQL、postgresql…等也紛紛納入一些NoSQL的元素,雙方都有開始接
Thumbnail
2023/05/02
範例句: 假設我們有一段文章以空白隔開的方式來切割詞彙,內容如下: 假設條件為: clauses:[提升,滿意度,問卷] 。 slop:4。 in_order: true ❗ 這裡的Slop代表範圍內不匹配的最大數量,從開始匹配的字詞框到最後加總一併進行計算。 查詢結構會是如此 請問上述條件是否能正
Thumbnail
2023/05/02
範例句: 假設我們有一段文章以空白隔開的方式來切割詞彙,內容如下: 假設條件為: clauses:[提升,滿意度,問卷] 。 slop:4。 in_order: true ❗ 這裡的Slop代表範圍內不匹配的最大數量,從開始匹配的字詞框到最後加總一併進行計算。 查詢結構會是如此 請問上述條件是否能正
Thumbnail
2023/05/01
通常我們如果希望一筆資料是能夠具備唯一性的狀況下, 勢必在新增前會進行檢查, 但是在我們的應用程式中, 先查詢再寫入勢必會造成一些時間差, 導致於多人同時操作時, 可能發生重複資料的狀況。 假設我們的應用是不允許名稱重複, 那我們的資料可能如下: 我們的業務邏輯為「當名稱存在時就更新、不存在就新增」
Thumbnail
2023/05/01
通常我們如果希望一筆資料是能夠具備唯一性的狀況下, 勢必在新增前會進行檢查, 但是在我們的應用程式中, 先查詢再寫入勢必會造成一些時間差, 導致於多人同時操作時, 可能發生重複資料的狀況。 假設我們的應用是不允許名稱重複, 那我們的資料可能如下: 我們的業務邏輯為「當名稱存在時就更新、不存在就新增」
Thumbnail
看更多
你可能也想看
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
我們介紹了字串和列表的索引和切片操作。索引使用方括號[]來選擇字串或列表中的特定元素,並可以使用正向索引(從0開始)或反向索引(從最後一個元素為-1)來訪問元素。切片使用方括號[]和冒號:來選擇字串或列表中的一段子序列,指定起始位置和結束位置(不包含),並可以使用步長來控制間隔。
Thumbnail
我們介紹了字串和列表的索引和切片操作。索引使用方括號[]來選擇字串或列表中的特定元素,並可以使用正向索引(從0開始)或反向索引(從最後一個元素為-1)來訪問元素。切片使用方括號[]和冒號:來選擇字串或列表中的一段子序列,指定起始位置和結束位置(不包含),並可以使用步長來控制間隔。
Thumbnail
探索Python學習筆記中列表的建立、存取和常用方法。從使用中括號定義列表到了解索引、新增、刪除、修改等操作,並介紹append、remove、count等常用方法。
Thumbnail
探索Python學習筆記中列表的建立、存取和常用方法。從使用中括號定義列表到了解索引、新增、刪除、修改等操作,並介紹append、remove、count等常用方法。
Thumbnail
範例句: 假設我們有一段文章以空白隔開的方式來切割詞彙,內容如下: 假設條件為: clauses:[提升,滿意度,問卷] 。 slop:4。 in_order: true ❗ 這裡的Slop代表範圍內不匹配的最大數量,從開始匹配的字詞框到最後加總一併進行計算。 查詢結構會是如此 請問上述條件是否能正
Thumbnail
範例句: 假設我們有一段文章以空白隔開的方式來切割詞彙,內容如下: 假設條件為: clauses:[提升,滿意度,問卷] 。 slop:4。 in_order: true ❗ 這裡的Slop代表範圍內不匹配的最大數量,從開始匹配的字詞框到最後加總一併進行計算。 查詢結構會是如此 請問上述條件是否能正
Thumbnail
本篇主要是介紹MongoDB有哪些進階的索引, 了解原理及功能後, 在應用上才能規劃出更有效率的索引, 而主要會談到以下五個索引類型: 複合索引。 部份索引。 多鍵索引。 全文索引。 TTL索引。 進入到索引類型之前先提醒一下,一個集合的索引數不能超過64個。 限制: 最多只能31個欄位做一組複合索
Thumbnail
本篇主要是介紹MongoDB有哪些進階的索引, 了解原理及功能後, 在應用上才能規劃出更有效率的索引, 而主要會談到以下五個索引類型: 複合索引。 部份索引。 多鍵索引。 全文索引。 TTL索引。 進入到索引類型之前先提醒一下,一個集合的索引數不能超過64個。 限制: 最多只能31個欄位做一組複合索
Thumbnail
資料集中除了陣列這個外,還有另一個好幫手就是List,它跟陣列很像,我們直接來看一下怎麼用: 它的語法: 1.給予值 (1)單一新增: (2)陣列式新增: 例子: 2.取值 (1)foreach迴圈方式 (2)單一取值 3.取得List有多少個內容值 4.排序 想要反轉就再使用↓ 5.插入 6.複製
Thumbnail
資料集中除了陣列這個外,還有另一個好幫手就是List,它跟陣列很像,我們直接來看一下怎麼用: 它的語法: 1.給予值 (1)單一新增: (2)陣列式新增: 例子: 2.取值 (1)foreach迴圈方式 (2)單一取值 3.取得List有多少個內容值 4.排序 想要反轉就再使用↓ 5.插入 6.複製
Thumbnail
陣列運用、擷取字串   對於陣列裡的內容值除了把資料存進去外,若想要知道陣列維度、陣列大小、複製陣列的值到另一個陣列中、清除陣列的值等等的相關處理,甚至比較常用到的可能還需要做資料排列、查找資料等等,此時C#有一些屬性方法可以幫助到我們,不用寫複雜的迴圈,來看一看有哪些吧~
Thumbnail
陣列運用、擷取字串   對於陣列裡的內容值除了把資料存進去外,若想要知道陣列維度、陣列大小、複製陣列的值到另一個陣列中、清除陣列的值等等的相關處理,甚至比較常用到的可能還需要做資料排列、查找資料等等,此時C#有一些屬性方法可以幫助到我們,不用寫複雜的迴圈,來看一看有哪些吧~
Thumbnail
  陣列(Array)是什麼?它是一個很好用的東西哦!當我們要處理100個學生的成績的時候,如果沒有陣列的話,那麼我們的變數就要命名100個不同的變數,這樣的程式雖然不是不能執行,想一想,是不是有一點要在命名上會想破頭殼呢?因為要想100個不同的變數麻~   你說:「那就變數後面加入編號就好啦~如
Thumbnail
  陣列(Array)是什麼?它是一個很好用的東西哦!當我們要處理100個學生的成績的時候,如果沒有陣列的話,那麼我們的變數就要命名100個不同的變數,這樣的程式雖然不是不能執行,想一想,是不是有一點要在命名上會想破頭殼呢?因為要想100個不同的變數麻~   你說:「那就變數後面加入編號就好啦~如
Thumbnail
MongoDB 在排序時會將資料全部載入記憶體,之後在記憶體中進行排序,而預設開放給排序的記憶體只有 32 MB,因此在大量資料排序時就會引發該錯誤。
Thumbnail
MongoDB 在排序時會將資料全部載入記憶體,之後在記憶體中進行排序,而預設開放給排序的記憶體只有 32 MB,因此在大量資料排序時就會引發該錯誤。
Thumbnail
在上一篇文章中,我們講解了 MongoDB 的基本操作,接下來想講講如何更有效率的查詢想要找的資料 模糊查詢 就是查詢的條件只要部分符合就可以找到了,不用查找的關鍵字完全正確,我們直接來舉個例子比較好理解 先假設有以下這些資料 模糊查詢,查找的資料 item 值內有包含 book 就返回 這樣就會找
Thumbnail
在上一篇文章中,我們講解了 MongoDB 的基本操作,接下來想講講如何更有效率的查詢想要找的資料 模糊查詢 就是查詢的條件只要部分符合就可以找到了,不用查找的關鍵字完全正確,我們直接來舉個例子比較好理解 先假設有以下這些資料 模糊查詢,查找的資料 item 值內有包含 book 就返回 這樣就會找
Thumbnail
本篇文章將會講述陣列 (Array) 及 foreach 陳述式,陣列是寫程式中關於大筆資料的儲存方式,而 foreach 是處理大筆資料的處理方式之一。
Thumbnail
本篇文章將會講述陣列 (Array) 及 foreach 陳述式,陣列是寫程式中關於大筆資料的儲存方式,而 foreach 是處理大筆資料的處理方式之一。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News