1.反范式设计
先看看关系数据库做个关联查询怎么做的
比如2个表如下,一个订单有多个产品
products:{
'id',
'name',
'price',
'desc'
}
orders:{
'id',
'user',
'items':[product_id1,product_id2,product_id3]
}
这种做法关系数据库肯定没问题,一个表关联查询就行了。但mongodb则不得不查询多次,否则只能拿到产品id而已。大大降低查询性能
那要一次的话如下设计:
orders:{
'id',
'user',
'items':[
{ 'id':product_id1, 'name':..., 'price':..., 'desc':... },
{ 'id':product_id2, 'name':..., 'price':..., 'desc':... },
{ 'id':product_id3, 'name':..., 'price':..., 'desc':... }]
}
这样只需要一次查询便可,而且还能用elemMatch方法对items进一步过滤,就和关联查询差不多了。虽然DBRef也能做到,但DBRef不能进一步过滤。但这种方式缺点就是你在更新products时放弃了一致性。比如产品名字和价格变化,那老的数据还在order里,但这个需求是正确的,因为产品变了,但当时的订单的确不该变,不是吗。
何时需要反范式设计:
1.你认为引用的数据是否需要保持最新的?不是的话用反范式设计。(比如产品和订单的例子)
2.要保持最新,那更新频率多久一次?如果极少变化,那适合用反范式设计。
3.必须做到查询快速。那你得用反范式。
但你可以在修改时,实时或延时同步过去,看数据量是否庞大,太庞大就算了。
比如2个表如下,一个订单有多个产品
products:{
'id',
'name',
'price',
'desc'
}
orders:{
'id',
'user',
'items':[product_id1,product_id2,product_id3]
}
这种做法关系数据库肯定没问题,一个表关联查询就行了。但mongodb则不得不查询多次,否则只能拿到产品id而已。大大降低查询性能
那要一次的话如下设计:
orders:{
'id',
'user',
'items':[
{ 'id':product_id1, 'name':..., 'price':..., 'desc':... },
{ 'id':product_id2, 'name':..., 'price':..., 'desc':... },
{ 'id':product_id3, 'name':..., 'price':..., 'desc':... }]
}
这样只需要一次查询便可,而且还能用elemMatch方法对items进一步过滤,就和关联查询差不多了。虽然DBRef也能做到,但DBRef不能进一步过滤。但这种方式缺点就是你在更新products时放弃了一致性。比如产品名字和价格变化,那老的数据还在order里,但这个需求是正确的,因为产品变了,但当时的订单的确不该变,不是吗。
何时需要反范式设计:
1.你认为引用的数据是否需要保持最新的?不是的话用反范式设计。(比如产品和订单的例子)
2.要保持最新,那更新频率多久一次?如果极少变化,那适合用反范式设计。
3.必须做到查询快速。那你得用反范式。
但你可以在修改时,实时或延时同步过去,看数据量是否庞大,太庞大就算了。
2.不要把不断增加的数据嵌入
首先说说什么叫嵌入,数据库一对多,有2种做法,比如帖子和评论2个表,评论有个字段是帖子ID,那帖子和评论就是1对多,这个做法是引用。如果帖子有个字段叫评论(是个放ID的数组)这个就是内嵌。
不断增加的数据,mongodb对数组追加效率是很低的。不管10个1000个10万个都不算啥,但之后要保持不变,否则会慢得你受不了。比如一个帖子的评论,那就应该使用引用做法,而不是内嵌
不断增加的数据,mongodb对数组追加效率是很低的。不管10个1000个10万个都不算啥,但之后要保持不变,否则会慢得你受不了。比如一个帖子的评论,那就应该使用引用做法,而不是内嵌
3.嵌入做法预留空间
mongodb如果要增加内嵌的数组,是很慢的,要分配空间。但是只是修改内容是很快的。
所以如果你在插入数据时,明确知道总共多少条或最多多少条,可以先预留空间。放几个0或空字符串填充。
所以如果你在插入数据时,明确知道总共多少条或最多多少条,可以先预留空间。放几个0或空字符串填充。
4.尽量避免让mongoDB做计算
由于mongodb是种无脑的大型数据库,几乎不会做任何高效的处理。虽然group,mapreduce,和聚合功能都有,但效率不佳。所以尽量避免这样去做。
比如你有个表
{id, appleCount, orangeCount}分别有苹果和橘子总数,你当然可以用上面方式得到他们总数,但你最好增加一个totalCount字段来达到这个效果
比如你有个表
{id, appleCount, orangeCount}分别有苹果和橘子总数,你当然可以用上面方式得到他们总数,但你最好增加一个totalCount字段来达到这个效果
5.要有几个定时任务协助mongodb
1. 一致性修复器
使用反范式模式,但你有希望数据一致性
2.预分配器
创建今后文档需要用到的空间,否则到了应用会很慢
3.聚合器
通过增加表或增加字段的方式聚合数据
4.结构校验器
确保当前文档都有必填字段,否则矫正或通知。
当然以上都不能做到实时
使用反范式模式,但你有希望数据一致性
2.预分配器
创建今后文档需要用到的空间,否则到了应用会很慢
3.聚合器
通过增加表或增加字段的方式聚合数据
4.结构校验器
确保当前文档都有必填字段,否则矫正或通知。
当然以上都不能做到实时
6.ObjectId
无意义的主键用ObjectId存储,千万别转换成字符串。
1.方便查询
2.含有有用信息
3.字符串要多占两倍磁盘
1.方便查询
2.含有有用信息
3.字符串要多占两倍磁盘
7.如果有自己主键,请不要用默认主键
默认主键_id,如果你有自己的主键就不要用它,节省空间资源。
要知道1亿数据下,主键要占几百M内存。
要知道1亿数据下,主键要占几百M内存。
8.DBRef尽量避免使用
1.浪费一个字段$ref的空间2.完全可以自己用id做引用的范式设计代替这个功能
9.小文件数据不要用GridFS
GridFS查询性能较差。如果确定都是小文件(小于16M)请存储在表里
10.不要到处使用索引
比如你要返回集合中50%记录,就不该使用索引,比不用索引还慢。
所以,索引一般用在返回结果只是总体数据的一小部分时,超过一般就不要用了。
如果已经简历索引,但又在大规模查询不用索引,就用{"$natural":1} 强制禁用索引
写入操作大大多于查询操作,不要使用索引,否则写入会变慢。
所以,索引一般用在返回结果只是总体数据的一小部分时,超过一般就不要用了。
如果已经简历索引,但又在大规模查询不用索引,就用{"$natural":1} 强制禁用索引
写入操作大大多于查询操作,不要使用索引,否则写入会变慢。
11.建立分级文档加速扫描
假如你有一个表有10个字段,其中一个是zip,你查询如下
那mongodb会遍历每个字段来查找zip字段
使用内嵌文档我们能这样设计
把10个字段分成3~4个组,每个字段里面放字段
那么查询语句就变成
1.
db.users.find({
'zip'
:‘10003’})
使用内嵌文档我们能这样设计
把10个字段分成3~4个组,每个字段里面放字段
那么查询语句就变成
1.
db.users.find({'address.zip'
:‘10003’})
12.and 和 or查询
对于and,越是结果少的要放在条件的前面
对于or则相反,越是结果多的放在条件的前面
原理自己想想吧
对于or则相反,越是结果多的放在条件的前面
原理自己想想吧
13. 日志和备份节点
日志(-journal)和备份节点都会影响性能,而且都能做为数据恢复用,每台服务器2个都开启实在没啥必要。
建议是主纯备份节点可以用日志, 主节点和热备节点可以不用。如果没有纯备份节点,就用某个从节点开启日志
建议是主纯备份节点可以用日志, 主节点和热备节点可以不用。如果没有纯备份节点,就用某个从节点开启日志
14.开发时使用notablescan参数
开启这个选项,只要做全表扫描都会报错。开发时开启很有用,但生产环境不要开启
相关推荐
【学习笔记:我的学习笔记】 这是一份个人的学习笔记,主要涵盖了广泛的IT知识领域,...不断更新和补充学习笔记是提升技能和保持行业敏锐度的有效方式。记得结合实际项目和练习来巩固理论知识,以达到最佳的学习效果。
除了MySQL和NoSQL之外,其他重要的数据库产品如PostgreSQL、MongoDB和Redis等在大型互联网公司中得到广泛应用。这些产品的特点和版本更新,以及它们在市场中的定位,也是数据库管理员需要关注的重点。 在数据库安装...
此外,非关系型数据库,如NoSQL,适用于大数据、实时分析和分布式系统,如MongoDB和Cassandra。 在数据库设计中,概念设计、逻辑设计和物理设计是三个关键步骤。概念设计将业务需求转化为数据模型,如实体-关系(E-...
【FCC:ZQW的FCC前端开发笔记】是一份深入浅出的前端开发学习资源,主要基于Free Code Camp(FCC)的学习路径和挑战进行整理。FCC是一个全球知名的在线学习平台,专注于教授Web开发技能,包括HTML、CSS、JavaScript...
首先,"Java知识点补充"这部分是关于Java编程语言的学习笔记。Java是一种广泛使用的面向对象的编程语言,它的特点是跨平台、安全性高以及性能优异。这里可能包括了类、对象、接口、继承、多态性、异常处理、集合框架...
7. **数据库集成**:游戏往往需要保存用户数据,学习如何使用SQL和NoSQL数据库如MySQL、MongoDB等存储和检索游戏数据。 8. **调试与测试**:学习如何使用Java的调试工具进行问题定位,以及编写单元测试确保代码质量...
3. **数据库管理**:SQL语言、关系型数据库(如MySQL、Oracle)、NoSQL数据库(如MongoDB)的基本操作和设计原则。 4. **操作系统**:Windows、Linux、macOS的基本操作、命令行使用、系统管理与优化。 5. **软件...
9. **补充资料**:可能包括参考书籍、文章、工具和其他资源,帮助扩展学习。 10. **测试和作业**:用于检验学习效果,可能包含代码挑战和小测验。 总之,"The Web Developer Bootcamp 2020" 是一个全面的学习路径,...
研究 Códigorelacionado aos tutoriais do FreeCodeCamp" 暗示,这个压缩包可能包括了与freeCodeCamp教程配套的源代码,学员可能通过这些代码来实践所学的知识,或者可能是其他用户对教程内容的补充和扩展,以便...
4. **数据库管理**:可能会讲解SQL语法、数据库设计(ER模型)、事务处理、索引优化、关系型数据库(如MySQL、PostgreSQL)和非关系型数据库(如MongoDB、Redis)的区别及使用场景。 5. **软件工程**:包括敏捷开发...