MongoDB TTL索引的使用
阿新 • • 發佈:2020-03-17
[toc]
## 一、TTL索引介紹
>TTL全稱是(Time To Live),TTL索引能對一個單列配置過期屬性來`實現對文件的自動過期刪除`,我們可以在對欄位建立索引時新增`expireAfterSeconds`選項將索引轉換為TTL索引,該`欄位需要是date型別`,在以下幾種場景下即使索引設定了expireAfterSeconds屬性也不會生效
- 如果該欄位不是date型別,則文件不會過期
- 如果文件沒包含索引的這個欄位,則文件不會過期
## 二、TTL索引執行邏輯
>- MongoDB會開啟一個後臺執行緒讀取該TTL索引的值來判斷文件是否過期,但不會保證已過期的資料會立馬被刪除,因後臺執行緒`每60秒觸發一次刪除任務`,且如果刪除的資料量較大,會存在上一次的刪除未完成,而下一次的任務已經開啟的情況,導致過期的資料也會出現超過了資料保留時間60秒以上的現象。
>- 對於副本集而言,`TTL索引的後臺程序只會在primary節點開啟`,在從節點會始終處於空閒狀態,從節點的資料刪除是由主庫刪除後產生的oplog來做同步。
>- TTL索引除了有expireAfterSeconds屬性外,`和普通索引一樣`。
## 三、TTL索引的限制
- 只支援對`單個欄位建立TTL索引`,複合索引不支援expireAfterSeconds選項
- `_id列不支援`TTL索引
- `固定集合(capped collection)不支援`TTL索引
- 不支援用createIndex() 修改expireAfterSeconds屬性,但可以`用collMod命令修改`,或者重建索引,但重建對於大集合成本較高,建議用collMod方式
- 一個列只能建立普通索引或TTL索引,`不能同時對一個列建立這2種類型索引`(實際TTL索引本身就是普通索引,只是多了一個過期屬性)
- 如果一個`列已經存在索引,則需要先將該索引drop後才能重建為TTL索引`,不能直接轉換
## 四、TTL索引的使用場景
### 1. 指定具體的過期時間屬性
>該場景是在建立索引時明確指定一個expireAfterSeconds時間作為文件的過期時間
```javascript
// 對log_events集合的createdAt欄位建立TTL索引且設定expireAfterSeconds過期時間為3600秒(1小時)
onepiece:PRIMARY> db.log_events.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )
// 對文件插入資料,包含createdAt欄位,則該文件會在1小時候欄位刪除
onepiece:PRIMARY> db.log_events.insert( {
"createdAt": new Date(),
"logEvent": 2,
"logMessage": "Success!"
} )
```
### 2. 插入一個具體的過期時間
>該場景是在建立索引時將expireAfterSeconds設定為0,在這種情況下由插入到欄位的資料來控制文件何時過期,這種場景更加精細化,可靈活的控制文件的過期時間及控制在業務低峰期觸發文件過期
```javascript
// 對log_events集合的expireAt建立TTL索引,並設定expireAfterSeconds屬性為0
onepiece:PRIMARY> db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )
// 對文件插入資料,包含expireAt欄位,該文件過期時間就是expireAt欄位記錄的時間
onepiece:PRIMARY> db.log_events.insert( {
"expireAt": new Date('Jan 16, 2020 14:00:00'),
"logEvent": 2,
"logMessage": "Success!"
} )
```
### 3. TTL屬性的修改(collMod)
>對於TTL索引的expireAfterSeconds的屬性,可以用collMod方式進行修改
```javascript
// 建立TTL索引設定1小時過期屬性
onepiece:PRIMARY> db.log_events.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )
{
"createdCollectionAutomatically" : true,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
// 檢視索引定義
onepiece:PRIMARY> db.log_events.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.log_events"
},
{
"v" : 2,
"key" : {
"createdAt" : 1
},
"name" : "createdAt_1",
"ns" : "test.log_events",
"expireAfterSeconds" : 3600
}
]
// 修改索引定義,將一小時文件過期改為60秒
onepiece:PRIMARY> db.runCommand( { collMod: "log_events",
index: { keyPattern: { createdAt: 1 },
expireAfterSeconds: 60
}
})
// 返回值: { "expireAfterSeconds_old" : 3600, "expireAfterSeconds_new" : 60, "ok" : 1 }
```
## 五、Date型別
- `Date()` method which returns the current date as a string.
- `new Date()` constructor which returns a Date object using the ISODate() wrapper.
- `ISODate()` constructor which returns a Date object using the ISODate() wrapper.
```javascript
onepiece:PRIMARY> Date()
Thu Jan 16 2020 14:48:40 GMT+0800 (CST)
onepiece:PRIMARY> new Date()
ISODate("2020-01-16T06:48:48.655Z")
onepiece:PRIMARY> ISODate()
ISODate("2020-01-16T06:48:53.673Z")
```
## 六、參考文件
- https://docs.mongodb.com/manual/core/index-ttl/in