使用裸设备,还是使用文件系统?
描述 | pros | cons | |
裸设备 |
顺序读磁盘快比随机要快10-100倍,DB比OS更懂磁盘负载,因此很多DB是直接管理数据块如何存放的。 |
DB对裸设备的管理,比文件系统成熟得早,加上性能高,以及可忽略文件系统之间的差异,写裸设备也是推荐的。 |
要求DBA给DB划分整个磁盘; 同时裸设备接口随OS不同而不同,因此阻碍了商业化DB使用此方式; 最后裸设备不支持raid、san、nas。随着时间迁移,裸设备的优势已经不明显了。 |
文件系统 |
创建一个大文件,通过文件偏移量管理数据。 |
空磁盘上创建大文件,则文件内偏移量与物理偏移量大致一致; 因此性能上类似于裸设备了。 |
论文第六章举例讲了RAID的麻烦之处 |
不能使用文件系统缓存
如果DB使用文件系统的缓存机制,那么会带来重排序写问题、静默写延迟和性能问题。
- 事务落盘的时序无法保证;
- 无法保证Write Ahead Log原则
- 文件系统自带read-ahead预读和write-behind后写特性,这与DB的访问模式完全不符合:文件系统以来文件内物理偏移来做读写决策,而DB IO机制需要支持按照逻辑行为。
- 例1: DB能预测查询流的逻辑顺序,但是这些查询数据在物理上并不是连续的,OS的读写AP对预读I没有助益,DB需要结合“扫描B+树叶子”、“查询计划里的数据访问算法”、“查询计划里的future access pattern”信息,查询线程才能实现逻辑预读。
- 例2:DB刷日志缓存的时候,需要综合考虑锁状态和IO吞吐,这些信息智能靠DB自己获得,OS文件系统无法获得。
4. 性能上还有一个经典问题:双缓冲与内存拷贝造成的CPU占用率过高。
上面讨论过,为了保证正确,DB必须自己实现缓存,如果再使用OS的缓存,那么即带来内存的浪费,又带来拷贝内存的时间浪费。DB的瓶颈一般出现在内存上,之所以很多人不认为内存是瓶颈,而认为I/O是瓶颈,是因为很多商业DB产品厂商算好了内存与磁盘的比例这样正好能适应buffer pool;也算好了磁臂间磁盘交换IO的速率正好能适应所有操作系统的处理器,所以这种产品的I/O是瓶颈。
综上所述,数据库应该自己管理缓存。当代OS给数据库等程序提供钩子(如mmap/msync/madvise调用)以便规避double-buffering、保证直接刷盘、以及提供可定制策略。
为了快速访问数据库页面,所有DB都实现了一个巨大的共享缓冲池
帧:缓冲池是一个帧数组,每个帧对应一块DB block 大小的内存区域,这样一方面读写磁盘不需要翻译,另一方面也避免了内存碎片和压缩。
页面表:这个表每个元素对应一个帧,包含磁盘地址、脏标、引线数pin count和换页算法锁需要的信息。
缓冲池换页算法:这个算法的研究绕了一些弯路。早期关系型数据库领域有很多研究换页策略,主要是因对嵌套循环连接nested-loop join。嵌套循环连接的循环访问模式是一遍遍扫描比缓冲池还大的堆文件,按照OS换页策略如LRU/CLOCK对索引重用间隔的悲观策略,应对nested-loop join效果是很差的。当时人们想了很多种算法,有的策略是针对不同页面类型使用不同换页算法,例如按照Reiter域分离计划,B+树根节点和堆文件中页面的替换方式就不一样;有的甚至涉及到通过查询计划来动态修改换页策略。但是今天,大多数系统使用改进的LRU算法。