关系型数据库都需要产生一个最佳的执行计划从而在查询时耗费的时间和资源最少。通常情况下,所有的数据库都会产生一个以树形式的执行计划:计划树的叶子节点被称为表扫描节点。查询节点对应于从基表获取数据。

例如,这一个查询:SELECT *FROM TAB1,TAB2 where TAB2.ID>1000。假设计划树如下:

上面的计划树:“TBL1上的顺序扫描”和“TBL2上的索引扫描”分别对应于表TBL1和TBL2上的表扫描方法。TBL1上的顺序扫描:从对应页中顺序获取数据;索引扫描:使用索引扫描访问表2。选择一个正确的扫描方法作为计划的一部分对于查询性能非常重要。

深入理解PG的扫描方法之前,先介绍几个重要的概念。

HEAP:存储表整个行的存储域。如上所示,整个域被分割为多个页,每个页大小默认是8K。每个页中,item指针(例如上述页中的1,2)指向页内的数据。

Index Storage:只存储KEY值,即索引中包含的列值。也是分割成多个页,每个索引页默认8K。

Tuple Identifier(TID):TID为6个字节,包含两部分。前4个字节为页号,后2个字节为页内tuple索引。TID可以定位到特定记录。

当前版本,PG支持以下扫描方法:顺序扫描、索引扫描、索引覆盖扫描、bitmap扫描、TID扫描。依赖于表基数、选择的表、磁盘IO、随机IO、顺序IO等,每种扫描方法都非常有用。我们先创建一个表并预制数据,并解释这些扫描方法。

postgres=# CREATE TABLE demotable (num numeric, id int);
CREATE TABLE
postgres=# CREATE INDEX demoidx ON demotable(num);
CREATE INDEX
postgres=# INSERT INTO demotable SELECT random() * 1000,  generate_series(1, 1000000);
INSERT 0 1000000
postgres=# analyze;
ANALYZE

这个例子中,预制1亿条记录并执行analyze更新统计信息。

顺序扫描

顾名思义,表的顺序扫描就是顺序扫描对应表所有页的item指针。如果一个表有100页,每页有1000条记录,顺序扫描就会获取100*1000条记录并检查是否匹配隔离级别以及where条件。因此,即使只有1条记录满足条件,他也会扫描100K条记录。针对上表的数据,下面的查询会进行顺序扫描,因为有大部分的数据需要被selected。

postgres=# explain SELECT * FROM demotable WHERE num < 21000;QUERY PLAN
--------------------------------------------------------------------Seq Scan on demotable  (cost=0.00..17989.00 rows=1000000 width=15)Filter: (num < '21000'::numeric)
(2 rows)

注意,不计算和比较计划耗费,几乎不可能直到选用哪个扫描方法。但是为了使用顺序扫描,至少需要满足以下关键点:谓词部分没有可用的索引键;或者SQL查询获取的行记录占表的大部分。如果只有少数行数据被获取,并且谓词在一个或多个列上,那么久会尝试使用或者不使用索引来评估性能。

索引扫描

和顺序扫描不同,索引扫描不会顺序获取所有表记录。相反,依赖于不同索引类型并和查询中涉及的索引相对应使用不同的数据结构。然后索引扫描获取的条目直接指向heap域中的数据,然后根据隔离级别判断可见性。因此索引扫描分两步:

从索引数据结构中获取数据,返回heap中数据对应的TID;然后定位到对应的heap页直接访问数据。由于以下原因需要执行额外的步骤:查询可能请求可用索引更多的列;索引数据中不维护可见信息,为了判断可见性,需要访问heap数据。

此时可能会迷惑,索引扫描如此高效,为什么有时不用呢?原因在于cost。这里的cost涉及IO的类型。索引扫描中,为了获取heap中的对应数据,涉及随机IO;而顺序扫描涉及顺序IO,只有随机IO耗时的1/4。

因此只有当顺序IO的代价大于随机IO时,才会选择索引扫描。

针对上表和数据,执行下面查询时会使用索引扫描。随机IO代价小,从而查询标记快。

postgres=# explain SELECT * FROM demotable WHERE num = 21000;QUERY PLAN
--------------------------------------------------------------------------Index Scan using demoidx on demotable  (cost=0.42..8.44 rows=1 width=15)Index Cond: (num = '21000'::numeric)
(2 rows)

Index Only Scan

仅索引扫描和索引扫描类似,区别在于第二步,仅仅涉及到扫描索引数据。有两个条件:查询获取的数据只有key列,且该列是索引的一部分;所有获取的数据都是可见的。如下所示:

postgres=# explain SELECT num FROM demotable WHERE num = 21000;QUERY PLAN
-----------------------------------------------------------------------------
Index Only Scan using demoidx on demotable  (cost=0.42..8.44 rows=1 Width=11)Index Cond: (num = '21000'::numeric)
(2 rows)

Bitmap Scan

是索引扫描和顺序扫描的混合体。为了解决索引扫描的缺点并充分利用其优点。正如上面所说,对于索引数据结构中的数据,需要找到heap页中对应的数据。因此需要获取一次索引页,然后获取heap页,从而造成大量随机IO。Bitmap扫描方法平衡了不使用随机IO的索引扫描优点。

Bitmap index scan:首先获取索引数据并为所有TID创建bitmap。为了理解方法,可以认为bitmap包含所有页的哈希(基于页号),每个页的entry包含页内所有偏移的数组。

Bitmap heap scan:从页的bitmap中读取值,然后针对页和偏移扫描数据。最后检查可见性和条件并返回tuple。

下面查询使用bitmap扫描,因为他选择的记录很多(比如too much for index scan)但不是大量(too little for sequential scan)。

postgres=# explain SELECT * FROM demotable WHERE num < 210;QUERY PLAN
--------------------------------------------------------------------------Bitmap Heap Scan on demotable  (cost=5883.50..14035.53 rows=213042 width=15)Recheck Cond: (num < '210'::numeric)->  Bitmap Index Scan on demoidx  (cost=0.00..5830.24 rows=213042 width=0)Index Cond: (num < '210'::numeric)
(4 rows)

再看另一个查询,选择同样多的记录但是仅仅索引列。不需要heap页因次没有随机IO,因此这个查询选择index only scan而不是bitmap scan。

postgres=# explain SELECT num FROM demotable WHERE num < 210;QUERY PLAN
---------------------------------------------------------------------------Index Only Scan using demoidx on demotable  (cost=0.42..7784.87 rows=208254 width=11)Index Cond: (num < '210'::numeric)
(2 rows)

TID Scan

TID扫描是PG中非常特殊的一种方式,和Oracle中的基于ROWID查询类似:

postgres=# select ctid from demotable where id=21000;ctid
----------(115,42)
(1 row)
postgres=# explain select * from demotable where ctid='(115,42)';QUERY PLAN
----------------------------------------------------------Tid Scan on demotable  (cost=0.00..4.01 rows=1 width=15)TID Cond: (ctid = '(115,42)'::tid)
(2 rows)

此外,PG社区还在讨论其他的扫描方法:MySQL中的“Loose Index Scan”、Oracle中的“index skip scan”、DB2中的“jump scan”。这个扫描方法用在指定场景:选择的B-tree索引的key列值都不同。避免遍历所有相等的key值,而只遍历第一个唯一值然后跳到下一个大值。这项工作PG正在开发,同样被叫做“Index skip scan”,未来可以在release中看到这个特性。

原文

https://severalnines.com/database-blog/overview-various-scan-methods-postgresql

PostgreSQL扫描方法综述相关推荐

  1. 基于深度学习的表面缺陷检测方法综述-论文阅读笔记

    //2022.3.2日阅读笔记 原文链接:基于深度学习的表面缺陷检测方法综述 (aas.net.cn) 个人对本篇综述内容的大致概括 论文首先介绍了表面缺陷检测中不同场景下的成像方案,主要根据表面颜色 ...

  2. 论文阅读—图像分割方法综述(三)(arXiv:[cs:cv]20200410)

    前面介绍了分割领域常用网络架构及其相应的分割模型,本节主要介绍一些最受欢迎的图像分割数据集及其特征.此外还有评估基于深度学习的分割模型的常用指标.并报告了这些模型的定量结果和实验性能. 系列回顾 论文 ...

  3. 简单典型二阶系统_微波战术通信系统空域抗干扰方法综述

    点击上方蓝色字体,关注我们 相关链接: <移动通信>2020年第8期目录 5G 2B专网解决方案和关键技术 MEC硬件加速技术分析 5G URLLC端到端关键技术分析 5G信令组网架构增强 ...

  4. 论文《基于深度学习的表面缺陷检测方法综述》学习笔记

    <基于深度学习的表面缺陷检测方法综述>学习笔记 前段时间完成了<基于图像的零部件缺陷识别系统设计>毕业课程设计,过程中收获了很多,老师也分享了很多论文,在此记录一下学习的收获. ...

  5. A survey on feature selection approaches for clustering-聚类特征选择方法综述

    Hancer, E., Xue, B. & Zhang, M. A survey on feature selection approaches for clustering.Artif In ...

  6. 【西安交大】2020年最新深度学习目标检测方法综述

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 目标检测的任务是从图像中精确且高效地识别.定位出大量预定义类别的物体实例.随着深度 ...

  7. 【北大-阿里巴巴】深度哈希方法综述,23页pdf,A Survey on Deep Hashing Methods

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 最近邻搜索是寻找数据库中的数据点,使它们到查询的距离最小,这是计算机视觉.推荐系统 ...

  8. 文本分类解决方法综述

    文本分类解决方法综述 参考文章: (1)文本分类解决方法综述 (2)https://www.cnblogs.com/sxron/articles/7742692.html 备忘一下.

  9. 【技术综述】基于弱监督深度学习的图像分割方法综述​

    文章首发于微信公众号<有三AI> [技术综述]基于弱监督深度学习的图像分割方法综述​ 本文是基于弱监督的深度学习的图像分割方法的综述,阐述了弱监督方法的原理以及相对于全监督方法的优势,首发 ...

最新文章

  1. DeepMind的AI能指导人类的直觉吗?
  2. HTTP 错误 404.0 - Not Found 您要找的资源已被删除、已更名或暂时不可用。
  3. python开发安卓程序-python可以编写android程序吗?
  4. SprinBoot易学难精
  5. 云原生/低代码/数据科学/计算等方向内容整理志愿者招募了!
  6. oracle几何体数据类型,Oracle数据库之spatial操作geometry方法
  7. It seems that scikit-learn has not been built correctly.
  8. 求一天的起始和结束(时间戳)和一个月的第一天和最后一天
  9. world wide web publishing无法启动 127错误
  10. SSD目标检测网络tensorRT推理【附代码】
  11. 《The industrial age of hacking》略读
  12. 室内地图导航功能接入流程
  13. level2行情对炒股有什么帮助?
  14. 浅谈选择示波器时的“5倍法则”
  15. 固态硬盘的坏块管理,你知道和不知道的
  16. NB-IoT模组选型及项目初始必看!
  17. chatGPT查询api的余额
  18. 【游戏测试】客户端性能 - drawcall 工具链
  19. 使用Unity编写传统ARPG游戏人物操作方式(二)
  20. javascript错误:对象不支持此属性或方法

热门文章

  1. HM4064原厂5A四节锂电池充电管理集成电路IC
  2. Lenovo T460 Fn功能键切换
  3. 腾讯人力资源管理体系
  4. 投简历的邮件正文要写一些什么内容比较恰当
  5. android7.1 jack-admin 报错
  6. pandas dataframe rolling 移动计算
  7. 如何优雅的在ubuntu终端中使用复制粘贴
  8. Flutter 中文文档:Flutter 中的布局
  9. apache atlas 编译包下载
  10. 《长尾理论》读书笔记