Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MongoDB 提升性能的18原则 — 转载 #40

Open
pfan123 opened this issue May 24, 2019 · 0 comments
Open

MongoDB 提升性能的18原则 — 转载 #40

pfan123 opened this issue May 24, 2019 · 0 comments

Comments

@pfan123
Copy link
Owner

pfan123 commented May 24, 2019

MongoDB 是高性能数据,使用的过程中,偶尔还会碰到一些性能问题。MongoDB和其它关系型数据库相比,例如 SQL Server 、MySQL 、Oracle 相比来说,相对较新,很多人对其不是很熟悉,所以很多开发、DBA往往是注重功能的实现,而忽视了性能的要求。其实,MongoDB和 SQL Server 、MySQL 、Oracle 一样,一个数据库对象的设计调整、索引的创建、语句的优化,都会对性能产生巨大的影响。

为了充分挖掘MongoDB性能,现简单总计了以下18条,欢迎大家一起来持续总结完善。

  • 文档中的_id键推荐使用默认值,禁止向_id中保存自定义的值。

MongoDB文档中都会有一个_id键,默认是个ObjectID对象(标识符中包含时间戳、机器ID、进程ID和计数器)。MongoDB在指定_id与不指定_id插入时 速度相差很大,指定_id会减慢插入的速率。

  • 推荐使用短字段名。

与关系型数据库不同,MongoDB 集合中的每一个文档都需要存储字段名,长字段名会需要更多的存储空间。

  • MongoDB 索引可以提高文档的查询、更新、删除、排序操作,所以结合业务需求,适当创建索引。

  • 每个索引都会占用一些空间,并且导致插入操作的资源消耗,因此,建议每个集合的索引数尽量控制在5个以内。

  • 对于包含多个键的查询,创建包含这些键的复合索引是个不错的解决方案。复合索引的键值顺序很重要,理解索引最左前缀原则。

例如在test集合上创建组合索引{a:1,b:1,c:1}。执行以下7个查询语句:

db.test.find({a:”hello”})
db.test.find({b:”sogo”, a:”hello”})
db.test.find({a:”hello”,b:”sogo”, c:”666”})
db.test.find({c:”666”, a:”hello”})
db.test.find({b:”sogo”, c:”666”})
db.test.find({b:”sogo” })
db.test.find({c:”666”})
  • 以上查询语句可能走索引的是1、2、3、4
  • 查询应包含最左索引字段,以索引创建顺序为准,与查询字段顺序无关。
  • 最少索引覆盖最多查询。
  • TTL 索引(time-to-live index,具有生命周期的索引),使用TTL索引可以将超时时间的文档老化,一个文档到达老化的程度之后就会被删除。

创建TTL的索引必须是日期类型。TTL索引是一种单字段索引,不能是复合索引。TTL删除文档后台线程每60s移除失效文档。不支持定长集合。

  • 需要在集合中某字段创建索引,但集合中大量的文档不包含此键值时,建议创建稀疏索引。

索引默认是密集型的,这意味着,即使文档的索引字段缺失,在索引中也存在着一个对应关系。在稀疏索引中,只有包含了索引键值的文档才会出现。

  • 创建文本索引时字段指定 text,而不是1或者-1。每个集合只有一个文本索引,但是它可以为任意多个字段建立索引。

文本搜索速度快很多,推荐使用文本索引替代对集合文档的多字段的低效查询。

  • 使用 findOne 在数据库中查询匹配多个项目,它就会在自然排序文件集合中返回第一个项目。如果需要返回多个文档,则使用 find方法。

  • 如果查询无需返回整个文档或只是用来判断键值是否存在,可以通过投影(映射)来限制返回字段,减少网络流量和客户端的内存使用。

既可以通过设置{key:1}来显式指定返回的字段,也可以设置{key:0}指定需要排除的字段。

  • 除了前缀样式查询,正则表达式查询不能使用索引,执行的时间比大多数选择器更长,应节制性地使用它们。

  • 在聚合运算中,$match 要在 $ group前面,通过 $match 前置,可以减少$ group 操作符要处理的文档数量。

  • 通过操作符对文档进行修改,通常可以获得更好的性能,因为,不需要往返服务器来获取并修改文档数据,可以在序列化和传输数据上花费更少的时间。

  • 批量插入(batchInsert)可以减少数据向服务器的提交次数,提高性能。但是批量提交的 BSON Size 不超过48MB。

  • 禁止一次取出太多的数据进行排序,MongoDB 目前支持对 32M 以内的结果集进行排序。如果需要排序,请尽量限制结果集中的数据量。

  • 查询中的某些$操作符可能会导致性能低下,如$ne$not$exists$nin$or 尽量在业务中不要使用。

a) $exist: 因为松散的文档结构导致查询必须遍历每一个文档;

b) $ne: 如果当取反的值为大多数,则会扫描整个索引;

c) $not: 可能会导致查询优化器不知道应当使用哪个索引,所以会经常退化为全表扫描;

d) $nin: 全表扫描;

e) $or: 有多个条件就会查询多少次,最后合并结果集,应该考虑装换为 $in

  • 固定集合可以用于记录日志,其插入数据更快,可以实现在插入数据时,淘汰最早的数据。需求分析和设计时,可考虑此特性,即提高了性能,有省去了删除动作。

固定集合需要显式创建,指定Size的大小,还能够指定文档的数量。集合不管先达到哪一个限制,之后插入的新文档都会把最老的文档移出。

  • 集合中文档的数据量会影响查询性能,为保持适量,需要定期归档。

MongoDB 单条文档大小的限制 ---- Document 文档是构成 MongoDB 数据存储的最小单元, Document 表现形式犹如JSON一般,采用 K-V 对形式展开,类型要比 JSON 丰富。鉴于 JSON 只有6种数据类型 (字符串(string)、数值(number)、布尔(true、false)、 null、对象(object)、数组(array)),MongoDB在数据类型上并未采用简单的JSON进行数据的存储,而是使用了BSON (Binary Javascript Object Notation)。BSON 为了避免无端的大数据写入(类似二进制的图片、音频等),把内存全部吃满,而特意设置了单条文档的上限,因此一条文档上限若超过 16MB,则直接报错。

Other source

MongoDB优化查询性能

MongoDB 管理

MongoDB更需要好的模式设计 及 案例赏析

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant