bitmapscan中一个超巨大的cost值的怪现象
时间:2011-02-14
来源:互联网
本帖最后由 osdba 于 2011-02-14 16:40 编辑
create table t1(id int primary key,name varchar(40));
create table t2(id int primary key,id1 int,name varchar(40));
insert into t1 select generate_series(1,1000000),generate_series(1,1000000);
insert into t2 select generate_series(1,1000000),generate_series(1,1000000),generate_series(1,1000000);
create index idx_t2_id1 on t2(id1);
osdba=# set enable_bitmapscan=off;
SET
Time: 0.230 ms
osdba=# explain select * from t2 where t2.id1 in (10000,20000);
QUERY PLAN
-------------------------------------------------------
Seq Scan on t2 (cost=0.00..17906.00 rows=2 width=14)
Filter: (id1 = ANY ('{10000,20000}'::integer[]))
(2 rows)
Time: 0.764 ms
osdba=# set enable_seqscan=off;
SET
Time: 0.228 ms
osdba=# explain select * from t2 where t2.id1 in (10000,20000);
QUERY PLAN
-------------------------------------------------------------------------------
Bitmap Heap Scan on t2 (cost=10000000008.63..10000000016.53 rows=2 width=14)
Recheck Cond: (id1 = ANY ('{10000,20000}'::integer[]))
-> Bitmap Index Scan on idx_t2_id1 (cost=0.00..8.62 rows=2 width=0)
Index Cond: (id1 = ANY ('{10000,20000}'::integer[]))
(4 rows)
Time: 0.713 ms
可以看到cost值出来的一个巨大无比的值:cost=10000000008.63..10000000016.53
让人很奇怪,cost值怎么能算出这么大的一个值呢?
后面又细细想了想,操作过程中第 一步关闭了bitmapscan,这样SQL只能走seqscan了,第二步又关闭了seqscan了,这时执行器无法找到一个有效的执行方法,虽然bitmapscan被禁止了,但总得走一个执行方法,最后选择了bitmapscan,为了说明这个bitmapscan是一个禁止的方法,所以给了这个方法一个很大的cost值,这样来表示这个是一个不是用户期望的执行计划。
再后来发现,如果执行器必需走参数设置为被禁止的执行方法,它就会给这个cost一个很大的数字,例如建了一个表,如果这个表上没有索引,而我们又禁止了seqscan,这时执行器只能选seqscan,这时cost值就会设置一个很大的值:
osdba=# create table t3(id int,name varchar(40));
CREATE TABLE
Time: 168.563 ms
osdba=# insert into t3 select generate_series(1,1000000),generate_series(1,1000000);
INSERT 0 1000000
osdba=# set enable_seqscan=off;
SET
Time: 0.228 ms
osdba=# insert into t3 select generate_series(1,1000000),generate_series(1,1000000);
INSERT 0 1000000
Time: 4637.458 ms
osdba=# explain select * from t3 where id in (10000,20000);
QUERY PLAN
---------------------------------------------------------------------------
Seq Scan on t3 (cost=10000000000.00..10000009526.31 rows=3289 width=102)
Filter: (id = ANY ('{10000,20000}'::integer[]))
(2 rows)
create table t1(id int primary key,name varchar(40));
create table t2(id int primary key,id1 int,name varchar(40));
insert into t1 select generate_series(1,1000000),generate_series(1,1000000);
insert into t2 select generate_series(1,1000000),generate_series(1,1000000),generate_series(1,1000000);
create index idx_t2_id1 on t2(id1);
osdba=# set enable_bitmapscan=off;
SET
Time: 0.230 ms
osdba=# explain select * from t2 where t2.id1 in (10000,20000);
QUERY PLAN
-------------------------------------------------------
Seq Scan on t2 (cost=0.00..17906.00 rows=2 width=14)
Filter: (id1 = ANY ('{10000,20000}'::integer[]))
(2 rows)
Time: 0.764 ms
osdba=# set enable_seqscan=off;
SET
Time: 0.228 ms
osdba=# explain select * from t2 where t2.id1 in (10000,20000);
QUERY PLAN
-------------------------------------------------------------------------------
Bitmap Heap Scan on t2 (cost=10000000008.63..10000000016.53 rows=2 width=14)
Recheck Cond: (id1 = ANY ('{10000,20000}'::integer[]))
-> Bitmap Index Scan on idx_t2_id1 (cost=0.00..8.62 rows=2 width=0)
Index Cond: (id1 = ANY ('{10000,20000}'::integer[]))
(4 rows)
Time: 0.713 ms
可以看到cost值出来的一个巨大无比的值:cost=10000000008.63..10000000016.53
让人很奇怪,cost值怎么能算出这么大的一个值呢?
后面又细细想了想,操作过程中第 一步关闭了bitmapscan,这样SQL只能走seqscan了,第二步又关闭了seqscan了,这时执行器无法找到一个有效的执行方法,虽然bitmapscan被禁止了,但总得走一个执行方法,最后选择了bitmapscan,为了说明这个bitmapscan是一个禁止的方法,所以给了这个方法一个很大的cost值,这样来表示这个是一个不是用户期望的执行计划。
再后来发现,如果执行器必需走参数设置为被禁止的执行方法,它就会给这个cost一个很大的数字,例如建了一个表,如果这个表上没有索引,而我们又禁止了seqscan,这时执行器只能选seqscan,这时cost值就会设置一个很大的值:
osdba=# create table t3(id int,name varchar(40));
CREATE TABLE
Time: 168.563 ms
osdba=# insert into t3 select generate_series(1,1000000),generate_series(1,1000000);
INSERT 0 1000000
osdba=# set enable_seqscan=off;
SET
Time: 0.228 ms
osdba=# insert into t3 select generate_series(1,1000000),generate_series(1,1000000);
INSERT 0 1000000
Time: 4637.458 ms
osdba=# explain select * from t3 where id in (10000,20000);
QUERY PLAN
---------------------------------------------------------------------------
Seq Scan on t3 (cost=10000000000.00..10000009526.31 rows=3289 width=102)
Filter: (id = ANY ('{10000,20000}'::integer[]))
(2 rows)
作者: osdba 发布时间: 2011-02-14
不明白啊。迷迷糊糊。
作者: renxiao2003 发布时间: 2011-02-15
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28