pg索引上没有mvcc信息,即使select的列全是索引列,pg9.2之前,也要去表上查一次。
而pg9.2之后通过可见性映射表(visibility map)(xx_vm)。vm文件记录了一个块中的行是否对全部事务可见,如果可见,就不同访问行来判断可见性了。这种查询的执行计划被称为index-only scans。不用再去表上查一遍了。
如果对部分事务可见,部分不可见,那也会是index-only scans。这时并不是仅读索引即可了。
例子:
explain加analyze看真实执行计划,看到heap fetches:9,说明从块中读了9行,这实际上是块中所有的行了,所以index-only scans没效果。
判断index-only scans的效果,主要是这个表的块有多少对所有事务可见。在pg_class中查。看到“relallvisiable”是0,所以这个index-only scans无效。
这时手动vacuum一下表,发现relallvisiable是541了。
可以看到“Heap Fetches:0”,即从表的数据文件中读取的行数为0,是全部从索引中读取。
vm介绍:
为加快vacuum清理速度,并且降低对io的影响,pg8.4.1之后为每个数据文件夹了"xx_vm"文件,称为可见性映射表文件,简称VM文件。
vm文件为每个数据块存储一个标志位,用来标记块中是否存在需要清理的行。如果发现没有需要清理的行,就跳过该块的扫描。