本文很长,有8000字,建议大家先收藏再阅读。本文全面介绍了PG shared buffer pool的结构和一些常见的性能优化点和优化策略。在很多技术特征和概念上,与Oracle数据库做了一定的对比,可以让Oracle DBA通过参照更好的掌握PG的相关概念。
数据库的内存架构对数据库的性能影响十分大,PostgreSQL这些年的发展十分快,其内存架构的核心部分除了共享池外,都和Oracle有一定的类似。下图是PostgreSQL内存架构的一张逻辑示意图。这些结构中,shared memory对PostgreSQL数据库的性能影响很大。在PostgreSQL中最为重要的共享内内存缓冲包含Shared Buffer Pool,WAL Buffer和commit log。因为PostgreSQL数据库的SQL执行计划是会话级共享的,因此PostgreSQL数据库不需要类似Oracle的共享池结构。随着现代硬件技术的发展,CPU资源和内存资源都已经不会成为大型数据库的瓶颈了,因此SQL解析带来的开销已经不是系统中必须重点优化的工作了,反而是执行计划的效率更为重要,因此在现在的数据库产品中,全局共享CURSOR及其执行计划的设计逐渐不是主流了。

图 PostgreSQL逻辑架构图
本文我们重点讨论shared_buffers,这部分缓冲区对应于Oracle数据库就是db cache或者buffer cache。PostgreSQL的backend进程通过Buffer Manager模块来访问PostgreSQL的数据,而Buffer Manager通过Shared Buffer Pool来提高PostgreSQL数据访问的性能。backend访问PostgreSQL数据文件的过程和Oracle数据库十分类似,当backend要访问某个数据块的时候,会把需要访问的数据块的地址发送给Buffer Manager,如果这个数据块已经在Shared Buffer Pool中存在,那么Buffer Manager会返回包含这个数据的buffer id返回给backend,如果当前buffer中没有这个数据块,那么backend 通过调用Buffer Manager去申请一个buffer,然后把数据块的数据读入buffer,返回buffer id给后续处理使用。当然这是最简单的场景,对于分配buffer,还涉及了脏块的处理等过程,这里就不深入分析了,这些过程和Oracle数据库的DB CACHE是十分类似的,对Oracle数据库有所了解的DBA很容易理解这个过程。
为了实现这个过程,PostgreSQL的Buffer Manager分为三层:buffer table层、Buffer Descriptors层和buffer pool 层。buffer pool层是PostgreSQL buffer的物理实现,PostgreSQL的Buffer和Oracle一样,是一个固定长的数组,用于存放PostgreSQL的数据块。Buffer Descriptors层也是一个数组,是存储Buffer的元数据的层面,包含描述buffer及其状态的数据结构,此层的buffer描述和buffer pool中的数组是一一对应的。buffer table层是实现数据块寻址的,里面包含实现寻址的相关数据结构。整个体系如下图,这张图来自于著名的interdb.jp网站。

图1 PostgreSQL Buffer Manager
熟悉Oracle Buffer CACHE的人可能比较容易理解这个过程,在Oracle中也是Buffer HEAD(具体可参考X$BH)指向具体的Buffer,而通过HASH CHAINS来实现数据块的寻址。
PostgreSQL的数据块寻址也是通过HASH CHAINS的,这一点与Oracle类似。了解Oracle的DBA应该很容易回忆起Oracle是通过一个32位的rdba来实现Buffer定位的,其中10位是FILEID,22位是BLOCKID(BIGFILE TABLESPACE是32位的BLOCKID)。PostgreSQL这方面复杂一些,是通过一个叫做buftag的数据结构来唯一定位某个数据块的。


本文全面介绍了PostgreSQL的shared buffer pool结构和性能优化点,与Oracle数据库做了对比。分析了其数据访问过程、Buffer Manager分层结构、数据块寻址等。还探讨了并发争用问题及解决方法,强调了平衡Shared Buffers和OS CACHE的重要性,并给出了优化策略和参数设置建议。
最低0.47元/天 解锁文章
2292

被折叠的 条评论
为什么被折叠?



