文档数据库学习笔记
一、基本概念
1. 文档数据库特点
- Key-Value存储的演进:在简单键值对基础上增加了值内部的结构化能力
- 树状结构:文档通常采用JSON/BSON格式,天然形成树状嵌套结构
- 无模式/灵活模式:不需要预定义严格的数据结构
2. 数据层次结构
3. MongoDB中的对象标识
ObjectId("535234")是MongoDB自动生成的唯一标识符- 组成结构:4字节时间戳 + 5字节随机值 + 3字节递增计数器
- 确保在分布式环境中也能生成唯一ID
二、CRUD操作详解
1. Create 操作
// 插入单条文档
db.myCollection.insertOne({
"name": "Frank",
"age": 25,
"email": "frank@example.com"
})
// 插入多条文档
db.myCollection.insertMany([
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 28}
])
2. Read 操作
// 查找所有文档
db.myCollection.find()
// 带条件查询
db.myCollection.find({"age": {"$gt": 25}})
// 投影(指定返回字段)
db.myCollection.find({}, {"name": 1, "email": 1})
// 排序和限制
db.myCollection.find().sort({"age": -1}).limit(5)
3. Update 操作
// 更正笔记中的语法错误
db.myCollection.updateOne(
{"name": "Frank"},
{"$set": {"birthday_year": 1998}} // 正确语法
)
// 更新多个文档
db.myCollection.updateMany(
{"age": {"$lt": 30}},
{"$set": {"status": "young"}}
)
4. Delete 操作
// 删除单个文档
db.myCollection.deleteOne({"name": "Frank"})
// 删除多个文档
db.myCollection.deleteMany({"status": "inactive"})
三、存储结构与索引
1. 物理存储结构
- 分页管理:数据存储在硬盘中被划分为固定大小的"页"
- 页独立性:每个页相对独立,修改一页不影响其他页
- 存储效率:通过分页提高存储管理效率和I/O性能
2. 文档集合存储
- 使用类似文件系统的目录结构组织文档
- inode结构:包含文件基本信息和指针系统
- 直接指针:指向数据块
- 间接指针:指向包含更多指针的扩展页
3. 索引功能
- 索引是一种数据结构,提供快速查询能力
- 类似于书籍的目录,可以快速定位到包含所需数据的页
- MongoDB支持多种索引类型:单字段、复合、多键、地理空间等
四、思考题解答
思考题1:页大小设计考量
小页面(如2KB-4KB)的优势: - 有利于写密集型工作负载,只需修改少量数据时,小页减少写入放大 - 提高空间利用率,减少内部碎片(internal fragmentation) - 更适合随机访问模式,只需加载必要的最小数据单元 - 降低缓存污染,不需要的数据不会占用宝贵的内存空间
大页面(如4MB-8MB)的优势: - 有利于读密集型和顺序访问工作负载,一次I/O可获取更多数据 - 提高扫描操作的效率,适合数据分析类查询 - 减少TLB(转换检测缓冲区)压力,相同内存可映射更大地址空间 - 降低元数据开销,管理1000个4MB页比管理1,000,000个4KB页更高效
确定页大小时应考虑的因素: 1. 工作负载特征:随机访问还是顺序访问?读写比例如何? 2. 硬件特性:磁盘扇区大小、内存页面大小、SSD块大小等 3. 数据特性:文档平均大小和大小分布情况 4. 并发需求:小页通常支持更高并发度 5. 系统资源:内存大小决定可缓存的页数量
思考题2:页缓存 vs 文档缓存
页缓存的优势: - 保持数据局部性:相邻文档很可能被一起访问,整页缓存利用空间局部性 - 减少随机I/O:一次加载整页,后续访问同一页内文档无需额外磁盘操作 - 实现简单:与操作系统虚拟内存系统协同工作更自然 - 预读优化:可以预测性地预读后续页面
页缓存的劣势: - 内存利用率可能低:一页中可能只有少量文档被实际访问,缓存了整个页 - 缓存污染:加载大页可能挤出其他更有价值的数据 - 不适合大文档:文档大小超过页大小时需要特殊处理
文档缓存的优势: - 内存利用率高:只缓存实际被访问的文档,避免缓存无用数据 - 适合热点数据分散的场景:当热点文档分布在不同页时更有效 - 灵活性强:不受物理存储布局的限制 - 适合大文档:可以高效处理大小超过页大小的文档
文档缓存的劣势: - 可能破坏局部性:忽略文档之间的物理邻近关系 - 管理开销大:需要维护更复杂的缓存元数据 - 随机I/O增加:访问同一页的不同文档可能需要多次磁盘操作 - 实现复杂:需要额外的文档定位机制
考虑使用文档缓存的场景: 1. 工作集远小于总数据量且访问模式高度随机 2. 文档大小差异很大,有些远大于平均页大小 3. 内存极其有限,需要最大化缓存效率 4. 热点数据分布分散,没有明显的空间局部性 5. SSD存储:随机读取性能较好,减弱了页缓存的优势
现代数据库系统通常采用混合策略,例如以页缓存为主,但对大文档或特定访问模式采用文档级缓存。MongoDB的WiredTiger存储引擎默认使用页缓存,但通过精巧的内存管理实现高效的缓存利用率。