caching可以说是优化数据库系统表现的一个重要方面。
为什么需要cache?
不同的计算机元器件有不同的运行速度。在数据库系统中,我们主要关心的是磁盘I/O。磁盘存储器相较于SSD来说对于随机I/O的性能相当糟糕。大多数OLTP的工作量都是随机I/O,因此将它们从磁盘中取出会非常的慢。为了克服这个缺陷,PostgreSQL将数据缓存到内存中,来改善性能。甚至对于SSD来说,内存也是更快的。
所以几乎对所有的数据库来说,cache通常都是一个常见的概念。
cache中有什么?
PostgreSQL缓存这些内容:表数据、索引、查询执行计划。
当你查看一个查询执行计划,其中有一个阶段叫做计划阶段,这个阶段主要是为了选取适合此查询的最优计划。PostgreSQL也可以缓存计划,但这是在会话基础上的,一旦会话终止,这个缓存的计划就会被丢弃。
这时进行分析或最优化会变得很微妙,但这通常是不太重要的,除非你正在执行的查询确实是非常复杂或者有很多重复的查询。
我们可以查询pg_prepared_statements来看什么被缓存了。请注意跨会话是不可行的,这只在当前会话中可见。
存储区域
对caching来说,最重要的配置是shared_buffers。
shared_buffers是一个8KB块。在PostgreSQL检查磁盘中的数据之前,会首先对shared_buffers中的页面做一次查询,如果有一个命中,那么它会从相应位置返回这个数据,这样可以避免一次磁盘I/O。
缓冲区分配
当一个进程在LRU cache中请求一个页面(每当页面通过一个典型的SQL查询被访问时),它会请求一次缓冲区分配。
如果一个块已经在高速缓存中,它会加pin然后被返回。这个加pin的过程是一种增加用量计数的方法。当用量计数为0的时候,一个页就会被认为是unpinned。
只有在一个页面中不存在空闲的缓冲区/槽时,会发生缓冲区逐出。决定哪些页面应该被从内存中逐出和写入磁盘是一个经典的计算机科学问题。
PostgreSQL会保持追踪页面的用量计数,一旦这个值为0,就会被从内存中逐出和写入磁盘。而且当页面为脏时也会写入磁盘。
脏页
对DML查询来说,它们会被写入到相同的页面中。如果目前在内存中,它们会被直接写入内存中。如果不在,就要先从磁盘中获取,然后再将它们写入内存中。
脏页:页面已经被修改但是还没有被写入磁盘。
By Kalath