最近在看postgresql的查询计划,在查询中对表的扫描计划大概有如下几种:

Seq Scan
Index Scan
Bitmap Heap Scan
Index Only Scan

这里就把自己的理解写下来,欢迎大家批评指正:

1)对于Seq Scan很好理解,就是按照表的记录的排列顺序从头到尾依次检索扫描,每次扫描要取到所有的记录。这也是最简单最基础的扫表方式,扫描的代价比较大;

2)对于Index Scan,我们也很熟悉,对于给定的查询,我们先扫描一遍索引,从索引中找到符合要求的记录的位置(指针),再定位到表中具体的Page去取。等于是两次I/O,先走索引,再走取表记录,不同于全表扫描的是只取所需数据对应的Page,I/O量较小;

3)对于Bitmap Heap Scan不是很常见,我翻阅了postgresql的手册,找到以下几句话:

   A plain indexscan fetches one tuple-pointer at a time from the index, and immediately visits that tuple in the table.  A bitmap scan fetches all the tuple-pointers from the index in one go, sorts them using an in-memory "bitmap" data structure, and then visits the table tuples in physical tuple-location order.  The bitmap scan improves locality of reference to the table at the cost of more bookkeeping overhead to manage the "bitmap" data structure --- and at the cost that the data is no longer retrieved in index order, which doesn't matter for your query but would matter if you said ORDER BY.

上面的意思是说,普通的索引扫描( index scan)一次只读一条索引项,那么一个 PAGE 面有可能被多次访问;而 bitmap scan 一次性将满足条件的索引项全部取

出,并在内存中进行排序, 然后根据取出的索引项访问表数据。当 PostgreSQL 需要合并索引访问的结果子集时 会用到这种方式 ,通常情况是在用到 "or",“and”时会出现"Bitmap heap scan"。

4)所谓index only scan ,就是因为 建立 index时,所包含的字段集合,囊括了我们查询语句中的字段,这样,提取出相应的index ,就不必再次提取数据块了。

举个例子:对于表:

create table test(id int, name text, age int);
insert into test select generate_series(1,100000),'test'::text,generate_series(1,100000);

我们对id和age建立复合索引:

create index test_id_age on test(id ,age);

然后,执行查询:

explain select id, age from test  where id < 20 and age >0;

查询结果为:

postgres=# explain select id ,age from test where id < 20 and age >0;
QUERY PLAN
-------------------------------------------------------------------------------
Index Only Scan using test_id_age on test (cost=0.29..41.94 rows=20 width=8)
Index Cond: ((id < 20) AND (age > 0))
(2 rows)

这个查询里查询的id和age就在索引test_id_age上,在我们取出索引的时候,我们已经获取了(id,age)值的序列,因此就不必再去表中获取记录了,在Index上我们就获得了我们需要的数据,因此称为Index Only Scan。

那么这几种表的扫描的应用场景呢?是不是走索引就一定比全表扫描好呢?也不尽然。

我们知道全表扫描是直接扫描全表,而Index Scan是走一次索引再定位表所在的Page,那么我们可以推断:

当获取的数据分布很大(比如70%以上)时,用index scan 已经没有意义了,因为数据太多了,走索引再走表的代价已经超过了单纯走表的代价了。就不如用全表扫描了。

而数据分布较小(比如 1.7%),则索引的优势就体现出来了。可能bitmap index scan的性能就更好(相比于index scan,因为它减少了index的重复扫描)。

当数据更少的时候,用index scan可能就更好(索引重复的可能性较小且回避了在内存中排序的代价)。

需要引起注意的是, bitmap index scan也可以用在where 条件单一的时候。

而对于Index Only Scan,由于不需要扫描表的数据块,只走索引,那么在能满足条件的情况下几乎是最快的了(当然我也没有数据验证)。

对于索引的讨论一直是热门话题,这里只是简单的提到,下次遇到再详细的写写吧。

postgresql中的各种scan的比较的更多相关文章

  1. golang自己定义数据类型查询与插入postgresql中point数据

    golang自己定义数据类型查询与插入postgresql中point数据 详细代码例如以下: package main import ( "bytes" "databa ...

  2. PostgreSQL中的partition-wise join

    与基于继承的分区(inheritance-based partitioning)不同,PostgreSQL 10中引入的声明式分区对数据如何划分没有任何影响.PostgreSQL 11的查询优化器正准 ...

  3. PostgreSQL中的索引(一)

    引言 这一系列文章主要关注PostgreSQL中的索引. 可以从不同的角度考虑任何主题.我们将讨论那些使用DMBS的应用开发人员感兴趣的事项:有哪些可用的索引:为什么会有这么多不同的索引:以及如何使用 ...

  4. 在PostgreSQL中CREATE STATISTICS

    如果你用Postgres做了一些性能调优,你可能用过EXPLAIN.EXPLAIN向你展示了PostgreSQL计划器为所提供的语句生成的执行计划,它显示了语句所引用的表如何被扫描(使用顺序扫描.索引 ...

  5. 通过arcgis在PostgreSQL中创建企业级地理数据库

    部署环境: Win7 64位旗舰版 软件版本: PostgreSQL-9.1.3-2-windows-x64 Postgis-pg91x64-setup-2.0.6-1 Arcgis 10.1 SP1 ...

  6. SQLSERVER中的ALLOCATION SCAN和RANGE SCAN

    SQLSERVER中的ALLOCATION SCAN和RANGE SCAN 写这篇文章的开始,我还不知道ALLOCATION SCAN的工作原理是怎样的,网上资料少得可怜 求助了园子里的某位大侠,他看 ...

  7. PostgreSQL 中日期类型转换与变量使用及相关问题

    PostgreSQL中日期类型与字符串类型的转换方法 示例如下: postgres=# select current_date; date ------------ 2015-08-31 (1 row ...

  8. PostgreSQL 中定义自己需要的数据类型

    PostgreSQL解决某系数据库中的tinyint数据类型问题,创建自己需要的数据类型如下: CREATE DOMAIN tinyint AS smallint CONSTRAINT tinyint ...

  9. 在PostgreSQL中使用oracle_fdw访问Oracle

    本文讲述如何在PostgreSQL中使用oracle_fdw访问Oracle上的数据. 1. 安装oracle_fdw 可以参照:oracle_fdw in github 编译安装oracle_fdw ...

随机推荐

  1. nodejs npm install -g 全局安装和非全局安装的区别

    1. npm install xxx -g 时, 模块将被下载安装到[全局目录]中. [全局目录]通过 npm config set prefix "目录路径" 来设置. 比如说, ...

  2. 设备控制接口ioctl详解

    [转]Linux设备控制接口 序言设备驱动程序的一个基本功能就是管理和控制设备,同时为用户应用程序提供管理和控制设备的接口.我们前面的“Hello World”驱动程序已经可以提供读写功能了,在这里我 ...

  3. 【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 2_Linear regression with one variable 单变量线性回归

    Lecture2   Linear regression with one variable  单变量线性回归 2.1 模型表示 Model Representation 2.1.1  线性回归 Li ...

  4. CSV Format

    [CSV Format] The comma separated values format (CSV) has been used for exchanging and converting dat ...

  5. codeforce469DIV2——D. A Leapfrog in the Array

    题意: 给出1<=n<=10^18和1<=q<=200000,有一个长度为2*n-1的数组,初始时单数位置存(i+1)/2,双数位置是空的.每次找出最右边的一个数将它跳到离它最 ...

  6. Composer安装(windows)

    https://files.cnblogs.com/files/wlphp/Composer-Setup.zip 先下载这个安装包,一直下一步 然后设置composer全局中国景象 composer ...

  7. laravel中的文件上传到本地+七牛云上传

    首先在filesystems.php 配置好上传的文件的目录起名为upload 在Storage/目录下面 目录下面的app/upload 如果没有这个文件会自动创建 这里的名字upload名字是跟控 ...

  8. linux下的同步与互斥

    linux下的同步与互斥 谈到linux的并发,必然涉及到线程之间的同步和互斥,linux主要为我们提供了几种实现线程间同步互斥的 机制,本文主要介绍互斥锁,条件变量和信号量.互斥锁和条件变量包含在p ...

  9. sfidsk创建可启动分区问题

    前言 由于工作上需要经常要为嵌入式设备制作启动SD卡,因此本人使用sfdisk编写了自动分区.格式化和安装文件的脚本.(不选择fdisk是因为它是为用户交互设计的,在脚本上使用不够方便) 实际使用过程 ...

  10. c语言实践 1/1+1/2+1/3+1/4+...+1/n

    给定一个n求这个分式的和. int n = 1; float sum = 0; float frac = 0; int i = 1; scanf_s("%d",&n); w ...