DAY14 MongoDB 索引属性与进阶注意事项

DAY14 MongoDB 索引属性与进阶注意事项

昨天的文章介绍了各种索引以及建立方式,这篇会讲一些使用上的一些经验。

索引属性 (Index properties)

在建立索引时还有一些属性能设定,这些非常关键请务必先了解。

Unique

透过设定 index unique,使得该栏位变成唯一值(亦可用在多栏位)。使用方法是在後方加上{unique:true}即可,例如:

db.employee.createIndex({"department": 1}, {unique:true})

复合索引使用方式也是一样。

Unique index 可以建立在不存在的栏位上,当一笔资料写入时,会给予它 null 当作值; 下一笔进来後,若也没有这个栏位,则会发生 key duplicated

Partial

Partial 属性是设定该栏位符合条件才会建立索引,这样一来充分的减少 索引创建的成本与空间。
例如要针对 age > 30 以上的资料建立索引,语法如下:

db.employee.createIndex({"department": 1}, {partialFilterExpression:{ age: { $gt:30 }}})

在以下的查询中,会走 parptial index 的有哪些呢?

1. db.employee.find({"department": 1, "age": {$gt: 30}}})
2. db.employee.find({"department": 1, "age": {$lte: 30}}})
3. db.employee.find({"department": 1, "age": 40})
4. db.employee.find({"department": 1})

Sparse

稀疏索引是针对存在的栏位做索引,上面那个是符合条件才建立,而这个是存在才建立,一样省去建立与维护成本。这听起来很像是 partial index 的一种,是的,没错。partial index 应用范围更大,包含了 sparse 特性。

使用语法如下:

db.employee.createIndex( { "assets": 1 }, { sparse: true } )

TTL

TTL index 顾名思义是针对文件建立 TTL,对於资料生命周期非常好用,基本上绝大部分 collection 需要建立,除非是不太会增加的 global configuration 就不用。

db.employee.createIndex( { "expiredTime": 1 }, { expireAfterSeconds: 32 * 86400, name: "ttlIndex" })

Hidden

这应该是 4.4 版本蛮亮眼的功能,当同事们对於索引相持不同意见时,可以请 DBA 执行这个指令。此功能是隐藏某个索引,输入後在执行计画里面都无法看到,但如果有资料更新,还是会帮新的文件建立索引喔,不用太担心。

隐藏後可以观察效能的各种改变,若确实没有什麽 side effect,就可以真的删除掉此索引了。大幅减少建立、删除索引的时间、效能耗损。

// hide
db.employee.hideIndex( {"index_name"})

// unhide
db.employee.unhideIndex( {"index_name"})

索引注意事项1: 栏位顺序

建立索引栏位的顺序非常重要!!
假设我们建立了一把索引

{ "field_a": 1, "field_b": 1, "field_c": 1, "field_d":1}

查询条件如果是以下,都是ok的

  • field_a
  • field_a, field_b
  • field_a, field_b, field_c
  • field_a, field_b, field_c, field_d

但如果是以下

  • field_b
  • field_b, field_c
  • field_c
  • field_d

就很不恰当。尽管在 (execution) explain 可能看到走在 index 上,但效率也是极差,甚至你使用 hint 强迫走在索引上也没用。依照我的使用经验,建议查询条件要符合前两个栏位。

索引注意事项2: 排序栏位

我们很多时候会需要使用到排序功能,若要提升效能也必须把排序栏位加在索引内,这样才能有效提升查询效能。

例如索引 {field_a:1, field_b:1, field_c:1}

db.collection.find( {field_1: 5} ).sort({ field_b:1 }) // ok

db.collection.find( {field_1: 5, field_b:1} ).sort({ field_c:1 }) // ok

db.collection.find( {field_1: 5, field_b:1} ).sort({ field_d:1 }) // bad

索引注意事项3: 背景执行

建立索引时,可以在後面加上背景执行的设定,比较不会让整个资料库卡住。

db.employee.createIndex({"department": 1}, {unique:true}, {background:true})

索引注意事项4: 覆盖查询

这是理想上最佳状态,但实务上通常不太能满足。当建立的索引栏位包含查询结果栏位时,速度是最快的,因为不用实际去取得文件本身资料。

db.employee.find({ index_field: {$lte:5000 } }, { _id:0 , index_field:1 })

上述范例就是查询了有建立索引的栏位,且 project 这个栏位,这样 MongoDB 实际上就不用走到文件本身去取资料,而是在索引上即可完成查询。

索引注意事项5: 避免 intersection index

这个中文我也翻不上来,意思就是在一个查询使用两个以上索引。

  • 所以这样使用可不可以?可以
  • MongoDB 会同时使用两个索引吗?会的
  • 哪里不好?效能
  • 多不好?没有比复合栏位好

所以什麽是 intersection index?

假设我们有两把索引

{ field_a : 1}
{ field_b : 1}

但我的查询是...

db.collection.find({ field_a: {$gte:3} , field_b: 100)

/// or
db.collection.find({ field_a: {$gte:3}).sort( {field_b: -1} )

这种情境下就是 intersection index,通常可以藉由调整索引或是文件结构来避免。

索引注意事项6: 避免整点 TTL

首先要有个观念,什麽样资料适合用在 TTL?

当然不会是交易类型的重要资料,要知道,即便是使用排程自动删除或者TTL方式,都需要执行时间且要考虑到失败的可能性,因此重要且有时效性的资料不会这样做(心脏够大例外)。

除此之外,通常整点会有一些固定的排程在执行,考量到 TTL 相当於删除资料的概念,这个不是最紧急或重要的事会抢占去系统资源,同时 oplog (MongoDB抄写机制)会塞入大量资料,更不是一件好事,因此这点非常重要。

如果你能非常肯定资料量很小,且未来不会有大幅度的成长,那很多设计或操作倒是没什麽影响。


小技巧

  • 如何在已经有重复资料的 Collection 建立 Unique 索引?

加上 {dropDups:true} 即可!

db.employee.createIndex({name:-1},{unique:true,dropDups:true})
  • 我就是要在当这个栏位存在才设定unique,可以吗?

可以,透过 sparse。语法如下:

db.employee.createIndex({"department": 1}, {sparse: true, unique:true})

索引一直以来都是资料库非常重要的一环,了解与善用非常重要,尤其尽量避免带有RDBMS的观念,虽然有些是相通的,但看到现在也能了解很多特点是 MongoDB 才有的,很多眉角在设计上无法光靠教科书或者教学文章就能透彻理解,毕竟每个情境都不同,最重要的还是实际去执行测试以及评估。那麽要如何评估索引的好坏呢~接着就是明天的事了 explain


本系列文章会同步发表於我个人的部落格 Pie Note


<<:  应用 LINE Front-end Framework 轻松建立互动 (2)

>>:  JavaScript入门 Day09_ 有关数字的语法1

DAY15支持向量机演算法(续四)

昨天介绍完SMO算法第四步,今天就要来写这个方法在迭代中的限制, 基本上每次在计算完Ei之後就要看E...

Day23 URLSession 03 - PUT / PATCH

PUT / PATCH:修改资料 一样的模式再来一次,根据以上的Reqres API 来示范 首先一...

敏捷思维(Agile Mindset)

敏捷思维 敏捷(agile)是一种思维(mindset),由价值观(values),原则(prin...

拥抱「资料结构」的「演算法」(29) - 戴克斯特拉演算法求最短路径

前言 对图形的搜寻有了基本观念之後,接下来要在图形的边加入权重的部分,这样就能找到最短路径 生活常识...

【Day29】漫谈 AI 在音乐上其他的优秀作品

超强的 AI 作曲 在 2020 年的时候 NVIDIA 在 YT 上发表了这支影片,里头使用到的音...