广告
返回顶部
首页 > 资讯 > 数据库 >Postgresql中的位图扫描(bitmap scan)
  • 357
分享到

Postgresql中的位图扫描(bitmap scan)

Postgresql中的位图扫描(bitmapscan) 2020-01-10 16:01:28 357人浏览 才女
摘要

  从MySQL的MRR开始 开始之前,先从Mysql入手,看一下mysql中的MRR机制原理,也就是Multi-Range Read。MySQL中在按照非聚集索引的范围查找且需要回表的情况下,比如select * fr

Postgresql中的位图扫描(bitmap scan)

 

从MySQL的MRR开始

开始之前,先从Mysql入手,看一下mysql中的MRR机制原理,也就是Multi-Range Read。
MySQL中在按照非聚集索引的范围查找且需要回表的情况下,比如select * from t where c2>100 and c2<200;c2为非聚集索引
如果直接根据非聚集索引(二级索引)键中的聚集索引键去回表,会产生大量的随机性io读取(图1)。
为了避免频繁的回表造成的随机IO,读取完非聚集索引上符合条件的key值之后,对key值对应的聚集索引键(图2的rowid)排序,然后根据排序后的聚集索引键顺序地回表,从而避免大量的随机性IO。
因为Mysql的Innodb表都是聚集表,那么图2中的rowid排序后,是顺序性的映射到聚集索引的page,从而避回表过程中的随机性IO。

(图1) (图2)

以上原理清楚后,继续引申出来另外一个经典的问题:
MySQL中的Innodb总是聚集索引表,或者SqlServer中的聚集表,非聚集索引为什么要拿聚集索引键(而非物理地址)作为其行指针?
对于聚集表,表中数据的物理位置因为需要保证按聚集索引建有序,同时意味着其真正的物理的rowid可能会发生变化(比如聚集索引非线性写入的时候,会导致叶分裂,页分裂会导致原始记录的物理位置变化),此时非聚集索引的行指针rowid也要做修改,这样会导致聚集表中的数据发生物理位置变化的时候,非聚集索引也要做相应的变化,如果非聚集索引用对应的聚集索引键做指针的话,就不会发生该问题。

由以上两个问题做铺垫,来看看postgresql中如何处理类似的问题。

Postgresql中的位图扫描(bitmap scan)

如果遇到类似于上述的查询(select * from t where c2>100 and c2<200;c2为非聚集索引的)情况下,查询结果是一个范围,那么Postgresql在回表的过程中,如何避免类似于上述图1中的随机性IO?
先弄清楚Postgresql的数据存储特点,Postgresql表的数据都是以堆表(heap)的形式存储的,因此Postgresql中不存在所谓的聚集索引,同时意味着其记录在物理结构上可以是无序存储,不会产生所谓的页分裂(page split)。
那么Postgresql中的行指针,这里称作rowid,正常情况是不会因为新数据的写入导致类似于MySQL或者sqlserver中的页拆分(page split)。
然后再说Postgresql的bitmap scan,bitmap scan的作用就是通过建立位图的方式,将回表过程中对标访问随机性IO的转换为顺行性行为,从而减少查询过程中IO的消耗。
先从一个非常简单的demo入手,如下查询,是一个典型的根据非聚集索引且需要回表的查询,满足以上的条件。
可以看到在对idx_c5上执行了一个Bitmap Index Scan,由于Bitmap Index Scan记录的是符合条件的记录所在的block,而非记录的指针,然后对这些block排序后再进行回表,Bitmap Index Scan之后有一个Recheck Cond是因为解析block的时候需要Recheck 。
参考这里:The bitmap is one bit per heap page. The bitmap index scan sets the bits based on the heap page address that the index entry points to.

最后,bitmap scan之后,对表的访问,总是通过bitmap Heap Scan完成。也就是执行计划的第一行。
这里的bitmap scan与上文中提到的MySQL中的MRR的思路算是一致的,都是通过中间一个缓存来避免随机性的IO访问,提升查询效率。
与基于聚集索引的总是从B+树的根节点通过二分法查找访问相比,对于postgresql中的这种直接基于物理Id的访问,从这一点上看,效率并不一定低。

bitmap scan的访问优化是基于代价考虑的,对于类似的查询,不总是一定走bitmap scan,如下,当访问的数据范围足够小的时候,可能不会走bitmap scan。

另外,bitmap scan的优化可以是基于不同字段或者不同筛选条件的,比如 where a>m and b>n(BitmapAndPath),亦或是where a>x or b>y(BitmapOrPath)这种访问方式,都可以通过bitmap scan来优化实现。

只不过笔者这里还有一个问题,因为postgresql中对行的update都是直接删除原始记录,然后新写入一条记录来实现的,只要这条记录的物理页面不变,那么非聚集索引的行指针就不变,如果这个记录的物理页面发生了变话,是不是索引的指针也会发生变化?

相关参数

正常情况下,是否用到bitmap scan优化,postgresql 优化器是可以选择出来一种最优的方式来执行的,但不保证总是可以生成最优化的执行计划,可以通过禁用bitmap scan或者 seqscan来尝试对比和调优。
任何优化都是一个系统工程,而不是一个单点工程,通过不同资源的消耗比例来提升整体性能,bitmap scan也并非完美无瑕,其优化理念是通过bitmap 的生成过程中增加内存和CPU字段消耗来减少IO消耗。
如果是高性能存储或者有充足的内存,并不一定总是发生物理IO,那么IO并不一定会是瓶颈,相反机械地去做bitmap的生成的话,反倒是一种浪费。
此时可以根据具体的IO能力,比如磁盘的随机读和顺序读代价参数,或者是禁用bitm scan等,来做整体上的优化方案。


参考
https://dba.stackexchange.com/questions/119386/understanding-bitmap-heap-scan-and-bitmap-index-scan
Https://blog.csdn.net/weixin_33672400/article/details/89734245

您可能感兴趣的文档:

--结束END--

本文标题: Postgresql中的位图扫描(bitmap scan)

本文链接: https://www.lsjlt.com/news/7495.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Postgresql中的位图扫描(bitmap scan)
      从MySQL的MRR开始 开始之前,先从MySQL入手,看一下MySQL中的MRR机制原理,也就是Multi-Range Read。MySQL中在按照非聚集索引的范围查找且需要回表的情况下,比如select * fr...
    99+
    2020-01-10
    Postgresql中的位图扫描(bitmap scan)
  • MYSQL 中的GROUP BY 的方式 (1)(loose index scan松散扫描 tight index scan紧凑扫描)
    水平有限有误请指出,转载请说明出处 测试脚本: create table tgrploose(p_id int primary key auto_increment,s_id1 int,s_id2 in...
    99+
    2022-10-18
  • C++中的位运算和位图bitmap解析
    目录位运算总结移位运算位运算应用举例位图位运算总结 移位运算 移位运算是双目运算符,两个运算分量都是整形,结果也是整形。“<<” 左移:右边空出的...
    99+
    2022-11-13
  • PostgreSQL索引扫描成本估算中的函数分析
    这篇文章主要介绍“PostgreSQL索引扫描成本估算中的函数分析”,在日常操作中,相信很多人在PostgreSQL索引扫描成本估算中的函数分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,...
    99+
    2022-10-19
  • C#.NET实现扫描识别图片中的文字
    目录环境配置操作步骤调用API接口扫描并读取图片中的文字C#VB.NET注意事项环境配置 本文以C#及VB.NET代码为例,介绍如何扫描并读取图片中的文字。 本次程序环境如下: ...
    99+
    2022-11-12
  • 浅谈Redis位图(Bitmap)及Redis二进制中的问题
    Redis位图(Bitmap)及二进制的问题 SETBIT key offset value 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。位的设置或清除取决于...
    99+
    2022-11-12
  • .NET Core使用C#扫描并读取图片中的文字
    本文介绍如何通过C# 程序来扫描并读取图片中的文字,这里以创建一个.Net Core程序为例。下面是具体步骤,供参考。 程序测试环境: Visual Studio版本要求不...
    99+
    2022-11-12
  • 如何使用C#扫描并读取图片中的文字
    目录程序测试环境:详细步骤程序测试环境: Visual Studio版本要求不低于2017 图片扫描工具:Spire.OCR for .NET 图片格式:p...
    99+
    2022-11-12
  • C# .NET如何实现扫描识别图片中的文字
    C# .NET如何实现扫描识别图片中的文字,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。环境配置本文以C#及VB.NET代码为例,介绍如何扫描并读取图片中的文字。...
    99+
    2023-06-22
  • .NET Core怎么使用C#扫描并读取图片中的文字
    这篇文章主要讲解了“.NET Core怎么使用C#扫描并读取图片中的文字”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“.NET Core怎么使用C#扫描并读取图片中的文字...
    99+
    2023-06-22
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作