我很难找到关于如何在 PostgreSQL 中缓存索引的“普通”解释,所以我想对任何或所有这些假设进行现实检查:
- PostgreSQL 索引,就像行一样,存在于磁盘上,但可能会被缓存。
- 索引可能完全在缓存中,也可能根本不在。
- 它是否被缓存取决于它的使用频率(由查询计划器定义)。
- 出于这个原因,大多数“明智的”索引将一直在缓存中。
- 索引与
buffer cache
行位于相同的缓存(?)中,因此索引使用的缓存空间对行不可用。
我理解这一点的动机来自另一个问题,我问过在哪里建议可以在大多数数据永远不会被访问的表上使用部分索引。
在进行此操作之前,我想明确一点,使用部分索引会产生两个优点:
- 我们减少了缓存中索引的大小,为缓存中的行本身释放了更多空间。
- 我们减小了 B-Tree 的大小,从而加快了查询响应。
玩了一下pg_buffercache,我可以回答你的一些问题。
pg_buffercache
节目查询,答案是肯定的YES。值得注意的是,临时表数据不会在这里缓存。编辑
我找到了 Jeremiah Peschka关于表和索引存储的精彩文章。有了那里的信息,我也可以回答(2)。我设置了一个小测试,所以你可以自己检查这些。
总而言之,这表明索引和表可以逐页缓存,因此(2)的答案是否定的。
最后一个来说明临时表在此处未缓存:
当查询决定索引页有助于减少回答查询所需的表数据量时,就会获取索引页。只有导航完成的索引块被读入。是的,它们进入存储表数据的同一个 shared_buffers 池。两者都由操作系统缓存作为第二层缓存提供支持。
您可以轻松地在内存中拥有 0.1% 的索引或 100% 的索引。当您的查询只涉及表的子集时,大多数“'明智的'索引将一直在缓存中”的想法很难落空。一个常见的例子是如果你有时间导向的数据。通常,这些人通常在表格的最近端导航,很少浏览旧历史。在那里,您可能会发现导航到内存中最近结束所需的所有索引块,而导航较早记录所需的索引块很少。
实现的复杂部分不是块如何进入缓冲区缓存。这是关于他们何时离开的规则。My Inside the PostgreSQL Buffer Cache talk 和其中包含的示例查询可以帮助您了解那里发生了什么,并查看生产服务器上真正积累的内容。这可能令人惊讶。在我的PostgreSQL 9.0 High Performance书中也有更多关于所有这些主题的内容。
部分索引很有用,因为它们减小了索引的大小,因此既可以更快地导航,又可以留出更多的 RAM 来缓存其他内容。如果您对索引的导航使得您触摸的部分始终在 RAM 中,那么无论如何,这可能不会带来真正的改进。