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 索引的目标是避免全表扫描,提高查询效率,但有些时 ...
随机推荐
- asp.net一些面试题(转)
基础知识 什么是面向对象 面向对象OO = 面向对象的分析OOA + 面向对象的设计OOD + 面向对象的编程OOP: 通俗的解释就是万物皆对象,把所有的事物都看作一个个可以独立的对象(单元),它们可 ...
- 关于Unity中UI中的Button节点以及它的Button组件
Button是最常用的UI节点,包含的组件有 1.Image组件 显示Button的纹理,把Image贴图拖进Image组件中后,记得点击Set Native Size,显示贴图原始大小 2.Butt ...
- android LayoutInflater 笔记
LayoutInflater类用于查找布局文件并实例化.用于动态将布局加入界面中. 参考链接 http://blog.csdn.net/guolin_blog/article/details/1292 ...
- 第三百零七节,Django框架,models.py模块,数据库操作——表类容的增删改查
Django框架,models.py模块,数据库操作——表类容的增删改查 增加数据 create()方法,增加数据 save()方法,写入数据 第一种方式 表类名称(字段=值) 需要save()方法, ...
- e656. 创建基本图形
Shape line = new Line2D.Float(x1, y1, x2, y2); Shape arc = new Arc2D.Float(x, y, w, h, start, extent ...
- 关于在SQLITE数据库表中插入本地系统时间的做法
首先,我参考下面的博文地址:http://blog.csdn.net/liuzhidong123/article/details/6847104 sqlite3 表里插入系统时间(时间戳) 分类: s ...
- Android Looper详解
在Android下面也有多线程的概念,在C/C++中,子线程可以是一个函数, 一般都是一个带有循环的函数,来处理某些数据,优先线程只是一个复杂的运算过程,所以可能不需要while循环,运算完成,函数结 ...
- php一些常规动态设置与获取
error_reporting(E_ALL); ini_set('display_errors', TRUE); ini_set('display_startup_errors', TRUE);ini ...
- angularJs 页面{{xxx}}使用三目运算符
<td>{{::item.sex=='w'?'女':'男'}}</td>,记得引号.也可以不用::,用不用::的区别,自行百度
- ios开发之--ZHPickView输出格式不出现 +0000
这样写就不会输出 +0000了 NSDate *select = [_datePicker date]; NSDateFormatter *dateFormatter = [[NSDateFormat ...