Mongodb--数据建模

Mongodb数据建模

文档结构:内嵌(Embedded data)和引用(Reference)

数据关系选用结构特点
一对一嵌套内容固定,小数据量,选用嵌套模式查询快捷方便
一对多嵌套小数据量,选用嵌套模式可以一次查询完所有数据
一对多引用大数据量,超过16m文件大小,选用引用模式避免过大
多对多引用?拆分成两个一对多
树形父链接根据查询需要,查子树要多个查询
树形子链接经常用于图存储
树形祖先队列能快速的找到子树
树形物化路径祖先模式略慢于物化路径模式
树形集合模型和前两者不同,适合静态树,不能修改

官方示例:https://docs.mongodb.com/manual/applications/data-models/

索引

数据关系特点
_id索引绝大多数集合默认建立的索引;在该集合中是唯一的。
单键索引值为一个单一的值,例如字符串,数字或者日期
多键索引值具有多个记录,例如数组
复合索引查询条件不止一个
过期索引在索引过期后,会自动删除。适合存储一些在一段时间之后会失效的数据比如用户的登录信息、存储的日志
唯一索引唯一索引只允许一条索引字段为空的记录存在,之后就不允许插入
稀疏索引当 字段在文档中不存在,或为空值,则不进入索引,及不存成null,能提高性能
全文索引索引类型:2d索引用来存储和查找平面上的点,2dsphere索引,用于存储和查找球面上的点; 查找方式:查找距离某个点一定距离内的内的点,查找包含在某区域内的点
地理位置索引能快速的找到子树
哈希索引祖先模式略慢于物化路径模式

tips:过期索引
1. 存储在过期索引字段的值必须是ISODate,不能使用时间戳
2. 过期索引不能使用复合索引
3. 删除时间不是精确的,删除过程是由后台程序需每60s跑一次,存在误差

tips:全文索引
1. 一个集合只能有一个全文索引
2. 每次查询,只能指定一个 text3. text查询不能出现在nor查询中
4. 查询中如果包含了$text,hint不再起作用
5. 对中文全文索引支持不友好

tips:稀疏索引的适用场景

一种是希望在并非出现在集合所有文档内的字段上增加唯一性索引时。举例来说,你明确希望在每个产品的sku字段上增加唯一性索引。但是出于某些原因,假设产品在还未分配sku时就加入系统了。如果sku字段上有唯一性索引,而你希望插入多个没有sku的产品,那么第一次插入会成功,但后续插入都会失败,因为索引里已经存在一个sku为null的项了。这种情况下密集型索引并不适合,你所需要的是稀疏索引。
另一种适用稀疏索引的情况:集合中大量文档都不包含被索引键。例如,假设允许对电子商务网站进行匿名评论。这种情况下,半数评论都可能缺少user_id字段,如果那个字段上有索引,那么该索引中一半的项都会是null。出于两个原因,这种情况的效率会很差。第一,这会增加索引的大小。第二,在添加和删除带null值user_id字段的文档时也要求更新索引。如果很少(或不会)对匿名评论进行查询,那么可以选择在user_id上构建一个稀疏索引。

操作命令:
> db.test_u.getIndexes()  //_id索引
> db.test_u.findOne()
> db.test_u.ensureIndex({y:1}) //单键索引
> db.test_u.find({y:99})
> db.test_u.insert({x:[1,2,3,4,5]})//多键索引
> db.test_u.ensureIndex({x:1,y:1})//复合索引
> db.test_u.find({x:100,y:99})
> db.test_time.insert({time:new Date()})//过期索引
> db.test_time.ensureIndex({time:1},{expireAfterSeconds:10})
> db.articles.ensureIndex({key:"text"})//全文索引
> db.articles.ensureIndex({key_1:"text",key_2:"text"})
> db.articles.ensureIndex({"$**":"text"})
> db.articles.insert({"article":"aa bb cc dd ee"})
> db.articles.insert({"article":"aa bb ff gg"})
> db.articles.insert({"article":"aa bb cc hh ii"})
> db.articles.find({$text:{$search:"aa bb"}})
> db.articles.find({$text:{$search:"aa bb -cc"}})
> db.articles.find({$text:{$search:"\"aa\" \"bb\" \"cc\""}})
> db.articles.insert({"article":"aa bb"})//全文索引相似度
> db.articles.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}})
> db.articles.find({$text:{$search:"aa bb"}},{score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})
> db.test_u.ensureIndex({x:1,y:1,z:1},{name:"I_comp"})//命名索引名字
> db.test_u.dropIndex({x:1,y:1,z:1},{name:"I_comp"})//删除索引
> db.test_u.ensureIndex({x:1,y:1,z:1},{name:"I_multi"})
> db.test_u.dropIndex("I_multi")
> db.test_u.ensureIndex({x:1,y:1,z:1},{name:"I_multi",unique:true})//唯一索引
> db.test_u.ensureIndex({x:1,y:1,z:1},{name:"I_multi",sparse:true})//稀疏索引

索引创建分析

好处:加快查询速度
坏处:增加磁盘空间消耗,降低写入性能

如何评判索引构建情况

1.mongostat工具

[mongodb_study]#./bin/mongostat -h 127.0.0.1:12345

>for(i=0;i<100000;i++)db.test_1.insert({x:i})

2.profile集合

> db.getProfilingStatus()
> db.getProfilingLevel()
> db.setProfilingLevel(2)//2表示记录所有,0表示不记录
> show tables
> db.system.profile.find()//查找profile集合
> db.system.profile.find().sort({$natural:-1}).limit(1)

3.mongo日志
配置verbose参数:v到vvvvv

4.explain分析

> db.system.profile.find().sort({$natural:-1}).limit(5).explain()

写操作的原子性和数据一致性

1.mongo数据库连接
要考虑mongo数据一致性和保证写操作的原子性,首先要了解mongo的内部机制。服务器为每个数据库连接维护一个请求队列。最新的请求会放在队尾。
如果打开两个shell,连接到相同数据库,这时就存在两个连接,对应不同的队列。如果在一个shell里做写操作,另一个shell做查询,新插入数据可能不再查询结果中。想动手实现很难,但在一个频繁执行插入和查询的服务器上很可能会发生。
使用ruby、python、java驱动程序的尤其要注意该问题,三者都有自己的连接池。其实mongo已经是一个现成的连接池了,而且线程安全。这个内置的连接池默认初始了10个连接,每一个操作(增删改查等)都会获取一个连接,执行操作后释放连接。因此不要自己再创建连接池了。可以通过驱动程序的配置:

  • connectionsPerHost:每个主机的连接数
  • threadsAllowedToBlockForConnectionMultiplier:线程队列数,它以上面connectionsPerHost值相乘的结果就是线程队列最大值。如果连接线程排满了队列就会抛出“Out
    of semaphores to get db”错误。
  • maxWaitTime:最大等待连接的线程阻塞时间
  • connectTimeout:连接超时的毫秒。0是默认和无限
  • socketTimeout:socket超时。0是默认和无限
  • autoConnectRetry:这个控制是否在一个连接时,系统会自动重试
MongoOptions opt = mongo.getMongoOptions();
opt.connectionsPerHost = 10 ;//poolsize
opt.threadsAllowedToBlockForConnectionMultiplier  = 10;

更多查看http://mongodb.github.io/mongo-java-driver/3.4/javadoc/

2.mongo的副本备份
副本集的数据可能不是最新的,这会导致读取到的数据是一秒钟之前甚至一分钟之前的。处理这种问题的方式有几种,最简单的一种是将所有的读取请求都发到主数据库。也可以写个脚本自动检测副本集是否落后于主数据库,如果落后,将副本集设置为维护状态。

3.原子操作
https://docs.mongodb.com/manual/tutorial/model-data-for-atomic-operations/#data-modeling-atomic-operation

文档增长

文档增长主要表现在往一个数组push数据和增加新列field。如果使用MMAPv1 存储引擎,每个文档会有预分配空间,当空间满了会分配新的空间。分配空间的策略是双倍增长(比如32,64,128,256,512,1MB,2MB….),但上限是16MB。
将数据放同一文档的缺点:
1、document预分配空间占满以后会重新分配新的空间,将产生额外的I/O消耗;
2、重新分配空间时,本document的索引字段全部重新索引
因此不要老往一个文档里塞数据,要考虑是否数据建模设计出了问题。

分片

将数据拆分,存在集群的不同机器上的过程。何时分片需要权衡,通常不要太早分片,因为分片不仅增加部署的操作复杂度,还要求做出设计决策,而该决策决定后很难更改。也不能在系统运行太久出现问题后再分片,因为在一个过载的系统上不停机进行分片是非常困难的。

大集合和大量小集合文件的优化

大集合应该要选择拆分成多个集合,并将他们关联来,而不是将过大数据存在单个集合中。

大量小集合文件优化方式:
1.充分利用_id字段,它是一个唯一的自带索引的12byte大小的数据。可以把一些有意义的字段存到里面,但要自己控制唯一性。
2.缩短field字段名称
3.使用嵌套模式合并小集合文件
mongodb的限制和临界值:
https://docs.mongodb.com/manual/reference/limits/#Number-of-Namespaces

引用模式的两种类别选用

Manual references和DBRefs
大部分时候用手动引用。
官方示例:https://docs.mongodb.com/manual/reference/database-references/

数据建模拾遗

1.mongo索引一般是同步更新的,但也可以建立异步索引。如果没有实时要求查询数据,建立异步索引可以提高写入速度。
2.mongo存储金钱相关数据:
https://docs.mongodb.com/manual/tutorial/model-monetary-data/
3.mongo存储时间数据:
https://docs.mongodb.com/manual/tutorial/model-time-data/
4.mongodb 3.0 改变很多,从2.6版本升级到3.0要关注的细节很多,如权限等等。3.0在数据存储引擎上更换成了wiredTiger,在数据压缩方面很有效,解决大数据量问题的情况下,磁盘不够用的问题。

Focus on data usage and better design schemas with the help of MongoDB About This Book Create reliable, scalable data models with MongoDB Optimize the schema design process to support applications of all kinds Use this comprehensive guide to implement advanced schema designs Who This Book Is For This book is intended for database professionals, software developers, and architects who have some previous experience with MongoDB and now want to shift their focus to the concepts of data modeling. If you wish to develop better schema designs for MongoDB-based applications, this book is ideal for you. In Detail This book covers the basic concepts in data modeling and also provides you with the tools to design better schemas. With a focus on data usage, this book will cover how queries and indexes can influence the way we design schemas, with thorough examples and detailed code. The book begins with a brief discussion of data models, drawing a parallel between relational databases, NoSQL, and consequently MongoDB. Next, the book explains the most basic MongoDB concepts, such as read and write operations, indexing, and how to design schemas by knowing how applications will use the data. Finally, we will talk about best practices that will help you optimize and manage your database, presenting you with a real-life example of data modeling on a real-time logging analytics application. Table of Contents Chapter 1. Introducing Data Modeling Chapter 2. Data Modeling with MongoDB Chapter 3. Querying Documents Chapter 4. Indexing Chapter 5. Optimizing Queries Chapter 6. Managing the Data Chapter 7. Scaling Chapter 8. Logging and Real-time Analytics with MongoDB
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值