在实际SQL优化工作中,我们经常会发现SQL 执行计划明明是 “Index Only Scan”,但执行计划后面却有 “Heap Fetches: x” ,也就是说实际执行计划还是访问了表记录。这是为什么了?

一、举个例子

1、创建数据

create table t1(id1 integer,id2 integer,name text);
insert into t1 select generate_series(1,100),generate_series(1,100),repeat('a',1000);
create index ind_t1 on t1(id1,id2);

2、查看执行计划

test=# explain analyze select id2 from t1 where id1=1;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Index Only Scan using ind_t1 on t1 (cost=0.14..8.16 rows=1 width=4) (actual time=0.024..0.025 rows=1 loops=1)
Index Cond: (id1 = 1)
Heap Fetches: 1
Planning Time: 0.286 ms
Execution Time: 0.044 ms
(5 rows)

可以看到,虽然SQL 只访问一条记录,但 heap fetches 值是 1 ,也就是实际需要访问表。

3、原因分析

test=# select pg_relation_filepath('t1');
pg_relation_filepath
----------------------
base/16089/16428
(1 row)

查看该路径下是否有 vm 文件。没有visibility map,postgresql就不知道是否所有的行对当前事务都是可见的,因此需要去访问表获取数据。只有fsm ,没有vm

[kb21@dbhost03 data]$ ls -l base/16089/16428*
-rw------- 1 kb21 kb21 122880 Sep 20 09:54 base/16089/16428
-rw------- 1 kb21 kb21 24576 Sep 20 09:54 base/16089/16428_fsm

4、vacuum 后执行计划

test=# vacuum analyze t1;
VACUUM
test=# explain analyze select id2 from t1 where id1=1;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Index Only Scan using ind_t1 on t1 (cost=0.14..4.16 rows=1 width=4) (actual time=0.011..0.012 rows=1 loops=1)
Index Cond: (id1 = 1)
Heap Fetches: 0
Planning Time: 0.249 ms
Execution Time: 0.031 ms
(5 rows)

vacuum 后,heap fetches 变为 0

二、进一步分析

1、通过 sys_visibility 扩展进行分析

test=# create extension  sys_visibility;
CREATE EXTENSION
test=# \dx+ sys_visibility
Objects in extension "sys_visibility"
Object description
-----------------------------------------------
function pg_check_frozen(regclass)
function pg_check_visible(regclass)
function pg_truncate_visibility_map(regclass)
function pg_visibility_map(regclass)
function pg_visibility_map(regclass,bigint)
function pg_visibility_map_summary(regclass)
function pg_visibility(regclass)
function pg_visibility(regclass,bigint)

pg_visibility_map 函数的参数:regclass, blkno bigint, all_visible OUT boolean, all_frozen OUT boolean

2、删除记录

test=# begin;
BEGIN
test=# delete from t1 where id1=1;
DELETE 1
test=# rollback;
ROLLBACK
test=# select pg_visibility_map('t1'::regclass, 0);
pg_visibility_map
-------------------
(f,f)
(1 row)

test=# select pg_visibility_map('t1'::regclass, 1);
pg_visibility_map
-------------------
(t,f)
(1 row)

因为id1=1 是在数据块0,因此,数据块并不是all visible

3、验证执行计划

test=# explain analyze select id2 from t1 where id1=1;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Index Only Scan using ind_t1 on t1 (cost=0.14..4.16 rows=1 width=4) (actual time=0.016..0.017 rows=1 loops=1)
Index Cond: (id1 = 1)
Heap Fetches: 1
Planning Time: 0.054 ms
Execution Time: 0.033 ms
(5 rows) test=# explain analyze select distinct id1,id2 from t1;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Unique (cost=0.14..10.14 rows=100 width=8) (actual time=0.014..0.042 rows=100 loops=1)
-> Index Only Scan using ind_t1 on t1 (cost=0.14..9.64 rows=100 width=8) (actual time=0.013..0.024 rows=100 loops=1)
Heap Fetches: 7
Planning Time: 0.057 ms
Execution Time: 0.060 ms
(5 rows) test=# vacuum analyze t1;
VACUUM
test=# explain analyze select distinct id1,id2 from t1;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Unique (cost=0.14..10.14 rows=100 width=8) (actual time=0.009..0.034 rows=100 loops=1)
-> Index Only Scan using ind_t1 on t1 (cost=0.14..9.64 rows=100 width=8) (actual time=0.008..0.017 rows=100 loops=1)
Heap Fetches: 0
Planning Time: 0.213 ms
Execution Time: 0.051 ms
(5 rows)

至于在Vacuum之前 heap fetches 为什么是 7 , 没搞明白。但明确的是vacuum 之后,heap fectches 变为0.

为什么Index Only Scan却还需要访问表的更多相关文章

  1. Index Full Scan vs Index Fast Full Scan-1103

    [Oracle] Index Full Scan vs Index Fast Full Scan作者:汪海 (Wanghai) 日期:14-Aug-2005 出处:http://spaces.msn. ...

  2. index full scan/index fast full scan/index range scan

    **************************1************************************* 索引状态:          valid.      N/A .    ...

  3. 索引跳跃式扫描(INDEX SKIP SCAN)

    索引跳跃式扫描(INDEX SKIP SCAN) 索引跳跃式扫描(INDEX SKIP SCAN)适用于所有类型的复合B树索引(包括唯一性索引和非唯一性索引),它使那些在where条件中没有对目标索引 ...

  4. index unique scan 与index range scan等的区别

    存取Oracle当中扫描数据的方法(一) Oracle 是一个面向Internet计算环境的数据库.它是在数据库领域一直处于领先地位的甲骨文公司的产品.可以说Oracle关系数据库系统是目前世界上流行 ...

  5. PostgreSQL执行计划:Bitmap scan VS index only scan

    之前了解过postgresql的Bitmap scan,只是粗略地了解到是通过标记数据页面来实现数据检索的,执行计划中的的Bitmap scan一些细节并不十分清楚.这里借助一个执行计划来分析bitm ...

  6. Oracle 11G INDEX FULL SCAN 和 INDEX FAST FULL SCAN 对比分析

    SQL> drop table test; 表已删除. SQL> create table test as select * from dba_objects where 1!=1; 表已 ...

  7. 【每日一摩斯】-Index Skip Scan Feature (212391.1)

    INDEX Skip Scan,也就是索引快速扫描,一般是指谓词中不带复合索引第一列,但扫描索引块要快于扫描表的数据块,此时CBO会选择INDEX SS的方式. 官方讲的,这个概念也好理解,如果将复合 ...

  8. INDEX FAST FULL SCAN和INDEX FULL SCAN

    INDEX FULL SCAN 索引全扫描.单块读 .它扫描的结果是有序的,因为索引是有序的.它通常发生在 下面几种情况(注意:即使SQL满足以下情况 不一定会走索引全扫描) 1. SQL语句有ord ...

  9. index unique scan

    INDEX UNIQUE SCAN 索引唯一扫描.单块读 只可能发生在unique index/primary key 等值查找                      等待事件:db file s ...

随机推荐

  1. Linux文本三剑客-grep

    Global search REgular expression and Print out the line 全局搜索正则表达式并打印行 作用: 对标准输入的行进行分析,过滤指定的行. 模式: 格式 ...

  2. leetcode二叉树题目总结

    leetcode二叉树题目总结 题目链接:https://leetcode-cn.com/leetbook/detail/data-structure-binary-tree/ 前序遍历(NLR) p ...

  3. 摸鱼人常备5个Python迷你项目,玩一整天不是问题(附源码)

    大家好鸭,我是小熊猫 在使用Python的过程中,我最喜欢的就是Python的各种第三方库,能够完成很多操作. 下面就给大家介绍5个通过Python构建的项目,以此来学习Python编程. 一.石头剪 ...

  4. 数据库 OLAP、OLTP是什么?相同和不同?适用场景

    一.OLTP和OLAP是什么,二者比较 人类世界遵从基本的物理规律,数据世界里,关于数据的操作处理,也大体分为OLTP和OLAP两类. OLTP on-line transaction process ...

  5. Python 用configparser读写ini文件

    一.configparser 简介Python用于读写ini文件的一个官方标准库.具体详见官网链接 二.configparser 部分方法介绍 方法 描述 read(filenames) filesn ...

  6. 大家好,我是UCMP云管家,这是我的自我介绍

    随着云计算的不断普及,构建在计算.存储.网络.数据库等基础资源之上的云平台逐渐大行其道:而随着多种云平台技术路线的发展成熟,多个云厂商的云平台开始出现在企业IT市场.对于企业而言,为满足成本.按需.隐 ...

  7. 区间统计——ST算法

    一.引入 先举一个小栗子. 一数组有 \(n\) 个元素,有 \(m\) 次询问(\(n, m <= 10^5\)).对于每次询问给出 \(l, r\),求出 \([l, r]\)的区间和. 有 ...

  8. Redis 渐进集群介绍

    redis 凭借着强大的功能和可靠的稳定性,应用场景越来越广.逐渐成为软件开发工程师必备的技能之一. 本篇文章,暂不做基本功能的介绍.直接教大家如何部署redis集群. 集群演进主要分为2部分. 一. ...

  9. 算法竞赛进阶指南0x51 线性DP

    AcWing271. 杨老师的照相排列 思路 这是一个计数的题目,如果乱考虑,肯定会毫无头绪,所以我们从1号到最后一个依次进行安排. 经过反复实验,发现两个规律 每一行的同学必须是从左向右依次连续放置 ...

  10. 1.9. 触摸按钮(touch pad)测试

    1.9.1. 基础 Esp32部分GPIO内置了touch按钮功能(电容式),具体有touch功能的引脚在配置为touchpad后,单片机读入的电容值随是否被触碰发生变化,系统根据电容值的变化判断判断 ...