因为新型存储器件的飞速发展,DRAM内存器件大小越来越大,导致内存数据库(其实还有内存文件系统)需求越来越强烈,原始基于硬盘为主存储结构的数据库设计因此会有哪些变化呢?
传统硬盘数据库设计特点
首先总结下传统硬盘数据库设计特点为:
- 使用非易失硬盘作为主要存储,使用易失内存做缓存池(涉及内存与磁盘上以“页”为单位的数据同步)
- 页为单位的索引数据组织(页号、slot号、header、tuple、blob等概念设计)
- 所有请求都会先经过缓存池(worker线程需要pin住该页防止被swap到磁盘)
- 并发控制保证事务可以等待所需数据的磁盘读取时间,其他事务可以不受影响地并发执行,同时锁(lock)要保存到其他数据结构(不在页结构中)防止被swap到磁盘
- 使用WAL策略处理日志与恢复问题
- CPU时间统计:30%缓存池、30%锁、28%日志、12%才是真正操作
内存数据库设计要点
设计内存数据库(内存作为主要存储位置),首先不要考虑使用mmap,缺点:内存操作无法非阻塞了、内存结构与磁盘必须相同、数据库系统不知道哪些页实际在内存中,说白了就是操作系统通用设计不可能比数据库架构师专业设计更好!
在内存数据库设计中,IO问题退居二线(DRAM 60ns, SSD 25000~30000ns),需要考虑其他性能问题:
- lock/latch
- cache-line miss
- pointer chasing
- predicate evaluations
- data move©
- network
总结下内存设计要点为:
- 不需要缓存池和页结构,可以直接用指针取代id索引,考虑tuple数据使用定长或变长记录,一定得使用checksum保证数据准确性;
- 获得锁时间跟获得数据时间一样!导致可以允许牺牲一点并发度,即实现coarse-grained locking,因为内存数据IO足够快。并且可以将锁信息与数据信息保存在一起,增加CPU cache locality,mutex相对太慢,一定改用CAS指令;
- 索引设计问题凸显,需要多考虑日志设计,需要多考虑一下CPU cache locality;
- 查询处理方式巨大改变,不需要顺序扫描,传统一次处理一个tuple方式相对太慢,考虑vector-at-a-time;
- 仍然需要WAL日志(内存易失),可能可以简化,使用coarse-grained locking则只需要实现redo日志。仍然需要checkpoint操作,使用Copy-on-Write 实现。
原文 http://www.chaozh.com/how-to-design-memory-database-system/