postgresql中的各种scan的比较
最近在看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的比较的更多相关文章
- golang自己定义数据类型查询与插入postgresql中point数据
golang自己定义数据类型查询与插入postgresql中point数据 详细代码例如以下: package main import ( "bytes" "databa ...
- PostgreSQL中的partition-wise join
与基于继承的分区(inheritance-based partitioning)不同,PostgreSQL 10中引入的声明式分区对数据如何划分没有任何影响.PostgreSQL 11的查询优化器正准 ...
- PostgreSQL中的索引(一)
引言 这一系列文章主要关注PostgreSQL中的索引. 可以从不同的角度考虑任何主题.我们将讨论那些使用DMBS的应用开发人员感兴趣的事项:有哪些可用的索引:为什么会有这么多不同的索引:以及如何使用 ...
- 在PostgreSQL中CREATE STATISTICS
如果你用Postgres做了一些性能调优,你可能用过EXPLAIN.EXPLAIN向你展示了PostgreSQL计划器为所提供的语句生成的执行计划,它显示了语句所引用的表如何被扫描(使用顺序扫描.索引 ...
- 通过arcgis在PostgreSQL中创建企业级地理数据库
部署环境: Win7 64位旗舰版 软件版本: PostgreSQL-9.1.3-2-windows-x64 Postgis-pg91x64-setup-2.0.6-1 Arcgis 10.1 SP1 ...
- SQLSERVER中的ALLOCATION SCAN和RANGE SCAN
SQLSERVER中的ALLOCATION SCAN和RANGE SCAN 写这篇文章的开始,我还不知道ALLOCATION SCAN的工作原理是怎样的,网上资料少得可怜 求助了园子里的某位大侠,他看 ...
- PostgreSQL 中日期类型转换与变量使用及相关问题
PostgreSQL中日期类型与字符串类型的转换方法 示例如下: postgres=# select current_date; date ------------ 2015-08-31 (1 row ...
- PostgreSQL 中定义自己需要的数据类型
PostgreSQL解决某系数据库中的tinyint数据类型问题,创建自己需要的数据类型如下: CREATE DOMAIN tinyint AS smallint CONSTRAINT tinyint ...
- 在PostgreSQL中使用oracle_fdw访问Oracle
本文讲述如何在PostgreSQL中使用oracle_fdw访问Oracle上的数据. 1. 安装oracle_fdw 可以参照:oracle_fdw in github 编译安装oracle_fdw ...
随机推荐
- O2耳放 DIY 模拟放大
http://nwavguy.blogspot.com/2011/07/o2-headphone-amp.html 原文链接 O2耳放. O2是一个DIY项目.免费,开源.本篇博客也免费,开源. O2 ...
- freemodbus modbus TCP 学习笔记
1.前言 使用modbus有些时间了,期间使用过modbus RTU也使用过modbus TCP,通过博文和大家分享一些MODBUS TCP的东西.在嵌入式中实现TCP就需要借助一个以太网协议 ...
- export LD_LIBRARY_PATH 的使用
对linux不是很熟,之前只是听说过可以设置程序共享库位置也就是 使用 “export LD_LIBRARY_PATH” 今天用了用,感觉还挺不错,也很常用. 比如你编译了一个so 而这个so 同时又 ...
- Just a Hook(树状数组)
In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. T ...
- RT2870移植到s3c2416后续验证无线…
我的无线网卡显示的事ra0,所以把下面的wlan0换成ra0即可:视自己的情况而定 1. 打开无线网卡电源 iwconfig wlan0 txpower on 2. 列出区域内的无线网络 iwlist ...
- no newline at the end of file
[no newline at the end of file] 修复这个警告,在文件结尾回车一下就行了. 这么规定的初衷是,为了每一行都要以换行结束. 因为行尾的/表示连接下一行,如果一个文件最后一 ...
- 解决nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
nginx先监听了ipv4的80端口之后又监听了ipv6的80端口,于是就重复占用了.更加坑人的是你去看了端口占用它又把80端口释放了,是不是很囧. 解决方案是编辑nginx的配置文件 修改这一段:
- python拷贝文件小程序(windows)
#!/usr/bin/python import os source='F:\\lh.jpg' target='E:\\' copy_command="xcopy %s %s"%( ...
- 搭建大数据hadoop完全分布式环境遇到的坑
搭建大数据hadoop完全分布式环境,遇到很多问题,这里记录一部分,以备以后查看. 1.在安装配置完hadoop以后,需要格式化namenode,输入指令:hadoop namenode -forma ...
- ROS 不能安装 Ros Packages
我的linux版本是16.04,安装的是kinetic 1. E: Some index files failed to download. They have been ignored, or ol ...