postgresql----索引失效
什么是索引失效?如果where过滤条件设置不合理,即使索引存在,且where过滤条件中包含索引列,也会导致全表扫描,索引不起作用。什么条件下会导致索引失效呢?
1.任何计算、函数、类型转换
2.!=
3.NOT,相当于使用函数
4.模糊查询通配符在开头
5.索引字段在表中占比较高
6.多字段btree索引查询条件不包含第一列
7.多字段索引查询条件使用OR(有时也会走索引扫描,但查询效率不高)
测试表
test=# \timing
Timing is on.
test=# create table tbl_index(a bigint,b timestamp without time zone ,c varchar(12));
CREATE TABLE
Time: 147.366 ms
test=# insert into tbl_index select generate_series(1,10000000),clock_timestamp()::timestamp without time zone,'bit me';
INSERT 0 10000000
Time: 30982.723 ms
1.任何计算、函数、类型转换
crtest=# create index idx_tbl_index_a on tbl_index (a);
CREATE INDEX
Time: 19634.874 ms
test=#
test=# explain analyze select * from tbl_index where a = 1;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------
Index Scan using idx_tbl_index_a on tbl_index (cost=0.43..8.45 rows=1 width=23) (actual time=59.844..59.850 rows=1 loops=1)
Index Cond: (a = 1)
Planning time: 22.788 ms
Execution time: 60.011 ms
(4 rows) Time: 84.865 ms
test=# explain analyze select * from tbl_index where a + 1 = 1;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
Gather (cost=1000.00..84399.00 rows=50000 width=23) (actual time=7678.109..7678.109 rows=0 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on tbl_index (cost=0.00..78607.33 rows=20833 width=23) (actual time=7350.047..7350.047 rows=0 loops=3)
Filter: ((a + 1) = 1)
Rows Removed by Filter: 3333333
Planning time: 0.112 ms
Execution time: 7688.615 ms
(8 rows) Time: 7780.024 ms
test=# explain analyze select * from tbl_index where power(a,2) = 1;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
Gather (cost=1000.00..94815.67 rows=50000 width=23) (actual time=47.516..6902.399 rows=1 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on tbl_index (cost=0.00..89024.00 rows=20833 width=23) (actual time=4607.894..6892.174 rows=0 loops=3)
Filter: (power((a)::double precision, ''::double precision) = ''::double precision)
Rows Removed by Filter: 3333333
Planning time: 13.564 ms
Execution time: 6904.232 ms
(8 rows) Time: 7051.482 ms
test=#
test=# explain analyze select * from tbl_index where a::varchar = '';
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
Gather (cost=1000.00..94815.67 rows=50000 width=23) (actual time=1.239..6689.272 rows=1 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on tbl_index (cost=0.00..89024.00 rows=20833 width=23) (actual time=4449.890..6679.233 rows=0 loops=3)
Filter: (((a)::character varying)::text = ''::text)
Rows Removed by Filter: 3333333
Planning time: 1.029 ms
Execution time: 6692.329 ms
(8 rows) Time: 6723.530 ms
在表tbl_index.a字段创建btree索引,使用a=1索引生效,但是下面的例子运算、函数、类型转换却导致索引失效了。
where a + 1 = 1
where power(a,2) = 1
where a::varchar = '1'
如何解决呢?可参考前面的表达式索引解决:
create index idx_tbl_index_a on tbl_index ((a+1));
create index idx_tbl_index_a on tbl_index ((power(a,2)));
create index idx_tbl_index_a on tbl_index ((a::varchar));
2.!=
test=# explain analyze select * from tbl_index where a != 1;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
Seq Scan on tbl_index (cost=0.00..140899.00 rows=9999999 width=23) (actual time=0.049..11004.864 rows=9999999 loops=1)
Filter: (a <> 1)
Rows Removed by Filter: 1
Planning time: 0.206 ms
Execution time: 11585.859 ms
(5 rows) Time: 11587.146 ms
3.NOT,相当于使用函数
test=# explain analyze select * from tbl_index where a is null;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------
Index Scan using idx_tbl_index_a on tbl_index (cost=0.43..4.45 rows=1 width=23) (actual time=30.092..30.092 rows=0 loops=1)
Index Cond: (a IS NULL)
Planning time: 33.783 ms
Execution time: 41.838 ms
(4 rows) Time: 102.544 ms
test=# explain analyze select * from tbl_index where a is not null;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Seq Scan on tbl_index (cost=0.00..115899.00 rows=10000000 width=23) (actual time=3.062..6309.908 rows=10000000 loops=1)
Filter: (a IS NOT NULL)
Planning time: 0.099 ms
Execution time: 6877.566 ms
(4 rows) Time: 6878.156 ms
以上比较可知where a is null索引生效,但是where a is not null导致索引生效。类似导致索引失效的还有NOT IN,NOT LIKE等,但是NOT EXISTS不会导致索引失效。下面的例子可以看到tbl_index表仍进行索引扫描,但是性能仍有限制,使用NOT IN虽然索引失效,但性能比NOT EXISTS要高。这个和我之前的认识有些出入,之前测试发现NOT EXISTS比NOT IN性能高,看来情况不同,性能也是不一定的。
test=# explain analyze select * from tbl_index where a not in (select a from tbl_test );
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
Seq Scan on tbl_index (cost=14.50..140913.50 rows=5000000 width=23) (actual time=1.393..3717.312 rows=9999000 loops=1)
Filter: (NOT (hashed SubPlan 1))
Rows Removed by Filter: 1000
SubPlan 1
-> Seq Scan on tbl_test (cost=0.00..12.00 rows=1000 width=8) (actual time=0.038..0.236 rows=1000 loops=1)
Planning time: 0.134 ms
Execution time: 4147.857 ms
(7 rows) Time: 4148.615 ms
test=# explain analyze select * from tbl_index where not exists (select null from tbl_test where tbl_test.a = tbl_index.a);
QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------
--------------------
Merge Anti Join (cost=62.45..218187.26 rows=9999000 width=23) (actual time=1.698..16909.581 rows=9999000 loops=1)
Merge Cond: (tbl_index.a = tbl_test.a)
-> Index Scan using idx_tbl_index_a on tbl_index (cost=0.43..193110.43 rows=10000000 width=23) (actual time=0.035..14781.400 row
s=10000000 loops=1)
-> Sort (cost=61.83..64.33 rows=1000 width=8) (actual time=0.390..0.659 rows=1000 loops=1)
Sort Key: tbl_test.a
Sort Method: quicksort Memory: 71kB
-> Seq Scan on tbl_test (cost=0.00..12.00 rows=1000 width=8) (actual time=0.038..0.194 rows=1000 loops=1)
Planning time: 0.339 ms
Execution time: 17530.472 ms
(9 rows) Time: 17594.258 ms
4.模糊查询通配符在开头
test=# explain analyze select * from tbl_index where c like 'bit%';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Seq Scan on tbl_index (cost=0.00..140899.00 rows=10000000 width=23) (actual time=0.099..1685.317 rows=10000000 loops=1)
Filter: ((c)::text ~~ 'bit%'::text)
Planning time: 55.373 ms
Execution time: 2104.863 ms
(4 rows) Time: 2164.464 ms test=# explain analyze select * from tbl_index where c like '%me';
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Seq Scan on tbl_index (cost=0.00..140899.00 rows=10000000 width=23) (actual time=20.172..5507.741 rows=10000000 loops=1)
Filter: ((c)::text ~~ '%me'::text)
Planning time: 65.603 ms
Execution time: 6007.367 ms
(4 rows)
5.索引字段在表中占比较高
test=# insert into tbl_index values (10000001,'2015-05-23 00:00:00','haha');
INSERT 0 1
Time: 88.226 ms
test=# explain analyze select * from tbl_index where c = 'bit me';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Seq Scan on tbl_index (cost=0.00..140899.00 rows=10000000 width=23) (actual time=0.051..6758.236 rows=10000000 loops=1)
Filter: ((c)::text = 'bit me'::text)
Rows Removed by Filter: 1
Planning time: 0.128 ms
Execution time: 7237.900 ms
(5 rows) Time: 7238.685 ms
test=# explain analyze select * from tbl_index where c = 'haha';
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------
Index Scan using idx_tbl_index_c on tbl_index (cost=0.43..4.45 rows=1 width=23) (actual time=0.063..0.065 rows=1 loops=1)
Index Cond: ((c)::text = 'haha'::text)
Planning time: 0.219 ms
Execution time: 2.869 ms
(4 rows) Time: 4.942 ms
test=# drop index idx_tbl_index_a;
DROP INDEX
Time: 134.873 ms
test=# drop index idx_tbl_index_c;
DROP INDEX
Time: 173.572 ms
6.多字段btree索引查询条件不包含第一列
test=# explain analyze select * from tbl_index where a = 10000001 and c = 'haha';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------
Index Scan using idx_tbl_index_a_c on tbl_index (cost=0.43..6.20 rows=1 width=23) (actual time=23.254..23.257 rows=1 loops=1)
Index Cond: ((a = 10000001) AND ((c)::text = 'haha'::text))
Planning time: 36.050 ms
Execution time: 35.710 ms
(4 rows) Time: 78.816 ms
test=# explain analyze select * from tbl_index where c = 'haha';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Gather (cost=1000.00..68982.44 rows=1 width=23) (actual time=7869.579..7890.974 rows=1 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on tbl_index (cost=0.00..67982.34 rows=0 width=23) (actual time=7468.480..7468.480 rows=0 loops=3)
Filter: ((c)::text = 'haha'::text)
Rows Removed by Filter: 3333333
Planning time: 0.130 ms
Execution time: 7891.137 ms
(8 rows) Time: 7891.937 ms
test=# explain analyze select * from tbl_index where a = 10000001;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------
Index Scan using idx_tbl_index_a_c on tbl_index (cost=0.43..8.45 rows=1 width=23) (actual time=0.154..0.156 rows=1 loops=1)
Index Cond: (a = 10000001)
Planning time: 0.257 ms
Execution time: 0.206 ms
(4 rows) Time: 1.119 ms
7.多字段索引查询条件使用OR
test=# explain analyze select * from tbl_index where a = 10000001 or c = 'haha';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Gather (cost=1000.00..79399.11 rows=1 width=23) (actual time=7321.821..7323.593 rows=1 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Parallel Seq Scan on tbl_index (cost=0.00..78399.01 rows=0 width=23) (actual time=7307.413..7307.413 rows=0 loops=3)
Filter: ((a = 10000001) OR ((c)::text = 'haha'::text))
Rows Removed by Filter: 3333333
Planning time: 0.163 ms
Execution time: 7324.821 ms
(8 rows) Time: 7325.532 ms
test=# explain analyze select * from tbl_index where a = 10000001 and c = 'haha';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------
Index Scan using idx_tbl_index_a_c on tbl_index (cost=0.43..6.20 rows=1 width=23) (actual time=0.040..0.041 rows=1 loops=1)
Index Cond: ((a = 10000001) AND ((c)::text = 'haha'::text))
Planning time: 0.165 ms
Execution time: 0.093 ms
(4 rows) Time: 32.904 ms
postgresql----索引失效的更多相关文章
- 【转】Oracle索引失效问题
转自:http://www.cnblogs.com/millen/archive/2010/01/18/1650423.html 失效情况分析: <> 单独的>,<,(有时会用 ...
- SQL SERVER 中is null 和 is not null 将会导致索引失效吗?
其实本来这个问题没有什么好说的,今天优化的时候遇到一个SQL语句,因为比较有意思,所以我截取.简化了SQL语句,演示给大家看,如下所示 declare @bamboo_Code varchar(3); ...
- mysql索引失效
在做项目的过程中,难免会遇到明明给mysql建立了索引,可是查询还是很缓慢的情况出现,下面我们来具体分析下这种情况出现的原因及解决方法 索引并不是时时都会生效的,比如以下几种情况,将导致索引失效: ...
- Oracle索引失效问题:WHERE C1='' OR C2 IN(SubQuery),并发请求时出现大量latch: cache buffers chains等待
问题描述: 项目反馈某功能响应时间很长,高峰期时系统整体响应很慢... 获取相应的AWR,问题确实比较严重,latch: cache buffers chains等待,因为这些会话SQL执行时间太长, ...
- ORACLE索引失效原因归纳[转]
1.隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误. 由于表的字段tu_mdn定义为varchar2(20),但在查询时把该字段作为number类型以where条件传给Orac ...
- oracle 使用ID关键字作列名导致索引失效
oracle表空间变更导致主键索引失效,重建索引即可
- MYSQL索引失效的各种情形总结
1) 没有查询条件,或者查询条件没有建立索引 2) 在查询条件上没有使用引导列 3) 查询的数量是大表的大部分,应该是30%以上. 4) 索引本身失效 5) 查询条件使用函数在索引列上,或者对索 ...
- oracle 索引失效原因及解决方法
oracle 索引失效原因及解决方法 2010年11月26日 星期五 17:10 一.以下的方法会引起索引失效 1,<>2,单独的>,<,(有时会用到,有时不会)3,like ...
- mysql索引之四(索引使用注意规则:索引失效--存在索引但不使用索引)
但是如果是同样的sql如果在之前能够使用到索引,那么现在使用不到索引,以下几种主要情况: 1. 随着表的增长,where条件出来的数据太多,大于15%,使得索引失效(会导致CBO计算走索引花费大于走全 ...
- oracle 索引失效原因
转自 http://www.cnblogs.com/orientsun/archive/2012/07/05/2577351.html Oracle 索引的目标是避免全表扫描,提高查询效率,但有些时 ...
随机推荐
- 第三百一十六节,Django框架,中间件
第三百一十六节,Django框架,中间件 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间 ...
- 第三百零四节,Django框架,urls.py模块,views.py模块,路由映射与路由分发以及逻辑处理——url控制器
Django框架,urls.py模块,views.py模块,路由映射与路由分发以及逻辑处理——url控制器 这一节主讲url控制器 一.urls.py模块 这个模块是配置路由映射的模块,当用户访问一个 ...
- 第二百八十二节,MySQL数据库-MySQL视图
MySQL数据库-MySQL视图 1.视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用. 2.也 ...
- Windows 中 .\ 和 ..\ 的区别
.\ 表示项目文件所在目录之下的目录...\ 表示项目文件所在目录向上一级目录下的目录...\..\表示项目文件所在目录向上二级目录之下的目录.
- Python3.4下使用sqlalchemy
一. 1.用sudo apt-get install python3-numpy之后,会默认把numpy安装到 /usr/lib/python3/dist-packages目录下,而且版本比较低. ...
- (转)MPEG4码流简单分析
把MPEG4码流的分析和它的I,P,B Frame的判定方法在这里简要记录一下吧,供日后的翻看和大家的参考. 测试解码器测试了很久,由于需要将H264和MPEG4的码流进行分析和判断,并逐帧输入解 ...
- [ACM] POJ 3349 Snowflake Snow Snowflakes(哈希查找,链式解决冲突)
Snowflake Snow Snowflakes Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 30512 Accep ...
- c#后台访问接口
直接上代码 后台代码 //接口地址string url = "http://spherefg.topsmoon.com:6666/restapi/Comment/SubmitCommentF ...
- HBase学习之深入理解Memstore-6
MemStore是HBase非常重要的组成部分,深入理解MemStore的运行机制.工作原理.相关配置,对HBase集群管理以及性能调优有非常重要的帮助. HBase Memstore 首先通过简 ...
- keepalived双BACKUP加nopreempt失效、手动监控服务脚步。
keepalived双BACKUP加nopreempt不起作用,两个机器同时拥有vip, 排查几天发现是防火墙问题,啃爹. 打开 vi /etc/sysconfig/iptables 插入一条:-A ...