最近在看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. delphi 天气预报

    天气预报 var astream : tmemorystream; sStream : TStringStream; jv : TJSONValue; begin astream := tmemory ...

  2. html收藏

    全屏显示<input type="button" name="fullscreen" value="全屏显示" onclick=&qu ...

  3. collections、time和datetime模块

    主要内容: 一.collections模块 二.time模块 三.datetime模块 1️⃣  collection模块 1.什么是collections模块.干什么用? collections模块 ...

  4. 安装sshpass:No package sshpass available

    安装sshpass的时候,报了如下错误: No Package sshpass available 更改软件源之后也无效.直到看到StackOverFlow上的一个问题:https://stackov ...

  5. 201671010140. 2016-2017-2 《Java程序设计》java学习第一周

       java学习第一周        本周是新学期的开端,也是新的学习进程的开端,第一次接触java这门课程,首先书本的厚度就给我一种无形的压力,这注定了,这门课程不会是轻松的,同时一种全新的学习方 ...

  6. 【bzoj1018】[SHOI2008]堵塞的交通traffic

    1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 2887  Solved: 954[Submit ...

  7. 【总结整理】微信产品-张小龙-PM学习总结

    伟大的产品可以满足人类的情感需求.找到需求背后的心理诉求产品的终极目标是满足任性需求,不在产品中掺杂自己的道德感.“我有个好主意”,往往都是脱离用户需求的. 1,不直接满足用户需求2,用户需求是零散的 ...

  8. BeanUtils简单应用

    <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http:// ...

  9. Solidity 合约调用合约

    原文地址:https://medium.com/@k3no/making-a-birthday-contract-858fd3f63618 先将datetime合约部署:https://github. ...

  10. (回文串)leetcode各种回文串问题

    题目一:最长连续回文子串. 问题分析:回文串顾名思义表示前后读起来都是一样,这里面又是需要连续的.分析这个问题的结构,可以想到多种方法.暴力解决的方式,2层循环遍历得出各个子串,然后再去判断该子串是否 ...