上次去杭州,德哥跟我谈起批量写入性能很低的问题。这跟PG设计有关,每次I/O都以块为单位,批量写入时需要新空间同样一次扩展一个块。最近一直在考虑怎样改进,个人觉得读取有类似问题,对于BAS_BULKREAD(缓存访问策略之一)方式一次读入一个块肯定不如一次读入多个块,至少可以省下一些磁盘寻道与回转(见机械磁盘原理)时间。很久以前使用Oracle,它有一次读入多少个数据块的设置,现在这个参数应该还在。缓存写出的改写非常复杂,它也绕不开块批量读入这个问题。出于这几点考虑,我想当然的认为既然对读取同样有效,首先实现单次读取多个块。
在我设想的方案确定之后,我觉得如果改写PG内核有作用的话,利用系统API也一样有效,并且非常容易实现。虽然它的缺点是不易受数据库引擎控制,但是作为验证是否有效是足够的。
用pgbench准备了10亿条数据,100多G,利用 posix_fadvise 函数预读预读8个块,测试后却发现毫无影响,时间是一致的。我猜想是不是块数太少,于是改成预读128个块,结果同样。(很抱歉,我没有记录下具体测试数据)
因为我对Linux的文件系统处理一无所知,无法确定到底怎么回事,有以下几个猜测:
1、Linux本身有自动预读?这个可能性很小,查阅了一点资料,也没有得到证实; 2、我测试用单进程,整台机器的所有资源被它占用大半,磁盘请求几乎不间断的涌向磁盘控制器,其实跟块连续读是一样的?这个等有时间再做一次多个表并发测试。