MogDBopenGauss中的Bitmap Index Scan

ops/2024/10/21 4:11:58/

测试数据库版本MogDB5.0.6

orcl=> select version();version                                                                        
------------------------------------------------------------------------------------------------------------------------------------------------------(MogDB 5.0.6 build 8b0a6ca8) compiled at 2024-03-27 11:05:29 commit 0 last mr 1804  on x86_64-unknown-linux-gnu, compiled by g++ (GCC) 7.3.0, 64-bit
(1 row)

测试表test01,test02表结构和索引结构

orcl=> \d test01Table "scott.test01"Column     |              Type              | Modifiers 
----------------+--------------------------------+-----------owner          | character varying(30)          | object_name    | character varying(128)         | subobject_name | character varying(30)          | object_id      | numeric                        | data_object_id | numeric                        | object_type    | character varying(19)          | created        | timestamp(0) without time zone | last_ddl_time  | timestamp(0) without time zone | timestamp      | character varying(19)          | status         | character varying(7)           | temporary      | character varying(1)           | generated      | character varying(1)           | secondary      | character varying(1)           | namespace      | numeric                        | edition_name   | character varying(30)          | 
Indexes:"idx_test01_name" btree (object_name) TABLESPACE pg_default"idx_test01_objectid" btree (object_id) TABLESPACE pg_default"idx_test01_objectype" btree (object_type) TABLESPACE pg_default"idx_test01_owner" btree (owner) TABLESPACE pg_defaultorcl=> \d test02Table "scott.test02"Column     |              Type              | Modifiers 
----------------+--------------------------------+-----------owner          | character varying(30)          | object_name    | character varying(128)         | subobject_name | character varying(30)          | object_id      | numeric                        | data_object_id | numeric                        | object_type    | character varying(19)          | created        | timestamp(0) without time zone | last_ddl_time  | timestamp(0) without time zone | timestamp      | character varying(19)          | status         | character varying(7)           | temporary      | character varying(1)           | generated      | character varying(1)           | secondary      | character varying(1)           | namespace      | numeric                        | edition_name   | character varying(30)          | 
Indexes:"idx_test02_objectype" btree (object_type) TABLESPACE pg_default"idx_test02_owner" btree (owner) TABLESPACE pg_default

数据量

orcl=> select count(*) from test01;count   
----------44537344
(1 row)orcl=> select count(*) from test02;count 
-------86987
(1 row)

场景一:

where (col1,col2) in ((),(),())

orcl=> explain analyze select * from test01 where (object_id,owner) in ((10,'SYS'),(20,'SYS'),(30,'SYS'));QUERY PLAN                                                               
---------------------------------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on test01  (cost=36.70..5969.07 rows=666 width=195) (actual time=0.480..3.367 rows=1536 loops=1)Recheck Cond: ((object_id = 10::numeric) OR (object_id = 20::numeric) OR (object_id = 30::numeric))Filter: ((owner)::text = 'SYS'::text)Heap Blocks: exact=1536->  BitmapOr  (cost=36.70..36.70 rows=1527 width=0) (actual time=0.324..0.324 rows=0 loops=1)->  Bitmap Index Scan on idx_test01_objectid  (cost=0.00..12.07 rows=509 width=0) (actual time=0.125..0.125 rows=512 loops=1)Index Cond: (object_id = 10::numeric)->  Bitmap Index Scan on idx_test01_objectid  (cost=0.00..12.07 rows=509 width=0) (actual time=0.092..0.092 rows=512 loops=1)Index Cond: (object_id = 20::numeric)->  Bitmap Index Scan on idx_test01_objectid  (cost=0.00..12.07 rows=509 width=0) (actual time=0.106..0.106 rows=512 loops=1)Index Cond: (object_id = 30::numeric)Total runtime: 3.704 ms
(12 rows)

场景二:

a join b on a.col1=b.col1 or a.col2=b.col2

orcl=> explain analyze select * from test02 a join test01 b on a.object_id=b.object_id or a.object_name=b.object_name where a.data_object_id<100;QUERY PLAN                                                                    
-------------------------------------------------------------------------------------------------------------------------------------------------Nested Loop  (cost=10000000043.97..1000000936164.67 rows=179252 width=390) (actual time=0.212..108.800 rows=54784 loops=1)->  Seq Scan on test02 a  (cost=10000000000.00..1000000261633.75 rows=121 width=195) (actual time=0.034..6.344 rows=107 loops=1)Filter: (data_object_id < 100::numeric)Rows Removed by Filter: 86880->  Bitmap Heap Scan on test01 b  (cost=43.97..5560.26 rows=1438 width=195) (actual time=15.764..91.421 rows=54784 loops=107)Recheck Cond: ((a.object_id = object_id) OR ((a.object_name)::text = (object_name)::text))Heap Blocks: exact=54784->  BitmapOr  (cost=43.97..43.97 rows=1438 width=0) (actual time=11.154..11.154 rows=0 loops=107)->  Bitmap Index Scan on idx_test01_objectid  (cost=0.00..12.11 rows=514 width=0) (actual time=6.737..6.737 rows=54784 loops=107)Index Cond: (a.object_id = object_id)->  Bitmap Index Scan on idx_test01_name  (cost=0.00..31.15 rows=924 width=0) (actual time=4.319..4.319 rows=54784 loops=107)Index Cond: ((a.object_name)::text = (object_name)::text)Total runtime: 111.192 ms
(13 rows)

场景三:

where  a.col1='xxx' and a.col2='xxxx'

orcl=> explain analyze select * from test01 where object_type='TABLE' and owner='PM';QUERY PLAN                                                                       
-------------------------------------------------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on test01  (cost=32733.65..43652.98 rows=2853 width=195) (actual time=284.860..300.625 rows=1536 loops=1)Recheck Cond: (((owner)::text = 'PM'::text) AND ((object_type)::text = 'TABLE'::text))Rows Removed by Index Recheck: 9157Heap Blocks: exact=10354->  BitmapAnd  (cost=32733.65..32733.65 rows=2853 width=0) (actual time=283.267..283.267 rows=0 loops=1)->  Bitmap Index Scan on idx_test01_owner  (cost=0.00..1532.88 rows=82217 width=0) (actual time=3.688..3.688 rows=22528 loops=1)Index Cond: ((owner)::text = 'PM'::text)->  Bitmap Index Scan on idx_test01_objectype  (cost=0.00..31199.10 rows=1545446 width=0) (actual time=270.632..270.632 rows=1524736 loops=1)Index Cond: ((object_type)::text = 'TABLE'::text)Total runtime: 301.094 ms
(10 rows)

场景四:

where a.col1='xxx' or a.col2='xxxx'

orcl=> explain analyze select * from test01 where object_type='TABLE' or owner='PM';QUERY PLAN                                                                       
-------------------------------------------------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on test01  (cost=33544.38..1319775.96 rows=1624810 width=195) (actual time=309.248..2131.274 rows=1545728 loops=1)Recheck Cond: (((object_type)::text = 'TABLE'::text) OR ((owner)::text = 'PM'::text))Rows Removed by Index Recheck: 9962574Heap Blocks: exact=233378 lossy=185029->  BitmapOr  (cost=33544.38..33544.38 rows=1627663 width=0) (actual time=246.804..246.804 rows=0 loops=1)->  Bitmap Index Scan on idx_test01_objectype  (cost=0.00..31199.10 rows=1545446 width=0) (actual time=242.247..242.247 rows=1524736 loops=1)Index Cond: ((object_type)::text = 'TABLE'::text)->  Bitmap Index Scan on idx_test01_owner  (cost=0.00..1532.88 rows=82217 width=0) (actual time=4.554..4.554 rows=22528 loops=1)Index Cond: ((owner)::text = 'PM'::text)Total runtime: 2198.976 ms
(10 rows)

场景一,场景二是很有用的SQL优化手段

场景三可以用组合索引代替BitmapAnd,组合索引性能更高

场景四具体情况具体分析,有时候全表扫描性能更好,有时候BitmapOr性能更好

Bitmap Index Scan会扫描完所有符合where过滤条件的数据生成位图信息,然后再回表查询数据

当SQL语句中有limit,且通过索引返回数据量很大时,走Bitmap Index Scan性能很差

举个例子:

where条件是owner='SYS',返回数据量很大,再加上limit 10,限制只返回10行数据

禁止indexscan,禁止走全表扫描,这个时候只能走Bitmap Index Scan

orcl=> explain analyze select /*+ set(enable_indexscan off) no tablescan(test01) */ * from test01 where owner='SYS' limit 10;QUERY PLAN                                                                       
--------------------------------------------------------------------------------------------------------------------------------------------------------Limit  (cost=366859.97..366860.62 rows=10 width=195) (actual time=1717.458..1717.464 rows=10 loops=1)->  Bitmap Heap Scan on test01  (cost=366859.97..1625932.64 rows=19430158 width=195) (actual time=1717.456..1717.460 rows=10 loops=1)Recheck Cond: ((owner)::text = 'SYS'::text)Rows Removed by Index Recheck: 10Heap Blocks: lossy=1->  Bitmap Index Scan on idx_test01_owner  (cost=0.00..362002.43 rows=19430158 width=0) (actual time=1655.260..1655.260 rows=19348992 loops=1)Index Cond: ((owner)::text = 'SYS'::text)Total runtime: 1720.485 ms
(8 rows)

强制走index scan

orcl=> explain analyze select /*+ indexscan(test01) */ * from test01 where owner='SYS' limit 10;QUERY PLAN                                                                   
------------------------------------------------------------------------------------------------------------------------------------------------Limit  (cost=0.00..34.95 rows=10 width=195) (actual time=0.025..0.028 rows=10 loops=1)->  Index Scan using idx_test01_owner on test01  (cost=0.00..67903941.68 rows=19430158 width=195) (actual time=0.024..0.026 rows=10 loops=1)Index Cond: ((owner)::text = 'SYS'::text)Total runtime: 0.203 ms
(4 rows)

 从上面的例子看到,当where条件有limit,不要走Bitmap Index Scan,limit无法刹车

参数force_bitmapand默认是off

orcl=> show force_bitmapand;force_bitmapand 
-----------------off
(1 row)

只有在性能比较好的时候才会走BitmapAnd

例如下面这个SQL走BitmapAnd性能很差,默认不会走BitmapAnd

orcl=> explain analyze select /*+ no tablescan(test01) */ * from test01 where object_type='TABLE' and owner='SYS';QUERY PLAN                                                                    
-------------------------------------------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on test01  (cost=31367.65..1318662.84 rows=674226 width=195) (actual time=312.484..1952.144 rows=527360 loops=1)Recheck Cond: ((object_type)::text = 'TABLE'::text)Rows Removed by Index Recheck: 9971731Filter: ((owner)::text = 'SYS'::text)Rows Removed by Filter: 997376Heap Blocks: exact=232995 lossy=185029->  Bitmap Index Scan on idx_test01_objectype  (cost=0.00..31199.10 rows=1545446 width=0) (actual time=248.890..248.890 rows=1524736 loops=1)Index Cond: ((object_type)::text = 'TABLE'::text)Total runtime: 1978.530 ms
(9 rows)

想要强制走BitmapAnd,需要设置参数force_bitmapand为on

orcl=> explain analyze select /*+ no tablescan(test01) set(force_bitmapand on)  */ * from test01 where object_type='TABLE' and owner='SYS';QUERY PLAN                                                                       
--------------------------------------------------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on test01  (cost=393538.89..1570552.75 rows=674226 width=195) (actual time=2224.240..4265.460 rows=527360 loops=1)Recheck Cond: (((owner)::text = 'SYS'::text) AND ((object_type)::text = 'TABLE'::text))Rows Removed by Index Recheck: 16497594Heap Blocks: exact=66723 lossy=293166->  BitmapAnd  (cost=393538.89..393538.89 rows=674226 width=0) (actual time=2205.842..2205.842 rows=0 loops=1)->  Bitmap Index Scan on idx_test01_owner  (cost=0.00..362002.43 rows=19430158 width=0) (actual time=1675.964..1675.964 rows=19348992 loops=1)Index Cond: ((owner)::text = 'SYS'::text)->  Bitmap Index Scan on idx_test01_objectype  (cost=0.00..31199.10 rows=1545446 width=0) (actual time=397.919..397.919 rows=1524736 loops=1)Index Cond: ((object_type)::text = 'TABLE'::text)Total runtime: 4291.262 ms
(10 rows)

没有force_bitmapor参数,当where条件中有or,想要强制走BitmapOr,禁止全表扫描就行

orcl=> explain analyze select /*+ no tablescan(test01) */ * from test01 where object_type='TABLE' or owner='SYS';QUERY PLAN                                                                       
--------------------------------------------------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on test01  (cost=403352.22..1763663.64 rows=20301378 width=195) (actual time=1872.535..7452.448 rows=20346368 loops=1)Recheck Cond: (((object_type)::text = 'TABLE'::text) OR ((owner)::text = 'SYS'::text))Rows Removed by Index Recheck: 17144302Heap Blocks: exact=230865 lossy=551600->  BitmapOr  (cost=403352.22..403352.22 rows=20975604 width=0) (actual time=1809.041..1809.041 rows=0 loops=1)->  Bitmap Index Scan on idx_test01_objectype  (cost=0.00..31199.10 rows=1545446 width=0) (actual time=248.296..248.296 rows=1524736 loops=1)Index Cond: ((object_type)::text = 'TABLE'::text)->  Bitmap Index Scan on idx_test01_owner  (cost=0.00..362002.43 rows=19430158 width=0) (actual time=1560.741..1560.741 rows=19348992 loops=1)Index Cond: ((owner)::text = 'SYS'::text)Total runtime: 8269.155 ms
(10 rows)

只有在返回少量数据的情况下BitmapOr性能才高,返回的数据量大,全表扫描性能更高

orcl=> explain analyze select * from test01 where object_type='TABLE' or owner='SYS';QUERY PLAN                                                        
-------------------------------------------------------------------------------------------------------------------------Seq Scan on test01  (cost=0.00..1450525.16 rows=20301378 width=195) (actual time=0.022..5755.405 rows=20346368 loops=1)Filter: (((object_type)::text = 'TABLE'::text) OR ((owner)::text = 'SYS'::text))Rows Removed by Filter: 24190976Total runtime: 6556.389 ms
(4 rows)

总结:

1. where (col1,col2) in ((),(),()) 走Bitmap Index Scan 可能性能较高

2. a join b on a.col1=b.col1 or a.col2=b.col2 走Bitmap Index Scan 可能性能较高

3. BitmapAnd 建议用组合索引代替

4. BitmapOr 要注意观察最终返回的数据量,返回数据量少性能较高,返回数据量大,走全表扫描


http://www.ppmy.cn/ops/31758.html

相关文章

VISO流程图之子流程的使用

子流程的作用 整个流程图的框图多而且大&#xff0c;进行分块&#xff1b;让流程图简洁对于重复使用的流程&#xff0c;可以归结为一个子流程图&#xff0c;方便使用&#xff0c;避免大量的重复性工作&#xff1b; 新建子流程 方法1&#xff1a; 随便布局 框选3 和4 &#…

软件应用开发安全设计指南

1.1 应用系统架构安全设计要求 设计时要充分考虑到系统架构的稳固性、可维护性和可扩展性&#xff0c;以确保系统在面对各种安全威胁时能够稳定运行。 在设计系统架构时&#xff0c;要充分考虑各种安全威胁&#xff0c;如DDoS攻击、SQL注入、跨站脚本攻击&#xff08;XSS&…

2024年Q1季度干衣机家电线上市场数据分析

春季阴雨绵绵&#xff0c;空气湿度增加&#xff0c;为晾晒衣物带来不便。与此同时&#xff0c;新消费主义的崛起也促使消费者更加注重时间效率和生活品质&#xff0c;寻求能够快速、方便地处理衣物的解决方案。借此&#xff0c;干衣机的需求量有所上涨。 根据鲸参谋数据显示&a…

JS中的数据绑定方式,以及Angular中如何实现数据绑定

在 JavaScript 中&#xff0c;单向数据绑定和双向数据绑定是两种常见的数据绑定方式&#xff1a; 1. 单向数据绑定&#xff1a; 单向数据绑定是指将数据模型的值绑定到视图上&#xff0c;当数据模型的值发生变化时&#xff0c;视图会自动更新以反映这些变化。但是&#xff0c;…

JAVA面试题--数据库基础

连接查询 1.左连接 &#xff08;左外连接&#xff09;以左表为基准进行查询,左表数据会全部显示出来,右表 如果和左表匹配 的数 据则显示相应字段的数据,如果不匹配,则显示为 NULL; 2.右连接 &#xff08;右外连接&#xff09;以右表为基准进行查询,右表数据会全部显示出来,右…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-8.2-链接脚本

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

实验15 MVC

二、实验项目内容&#xff08;实验题目&#xff09; 编写代码&#xff0c;掌握MVC的用法。 三、源代码以及执行结果截图&#xff1a; inputMenu.jsp&#xff1a; <% page contentType"text/html" %> <% page pageEncoding "utf-8" %> &…

SPRING-CLOUD从入门到精通

第一章> 1、微服务零基础 2、从X和H版本说起 3、Cloud组件 4、微服务架构 5、Eureka服务注册与发现 第二章> 6、Zookeeper 7、Consul 8、Ribbon均衡 9、OpenFeign 10、Hystrix断路器 第三章> 11、…