什么是索引失效?如果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----索引失效的更多相关文章

  1. 【转】Oracle索引失效问题

    转自:http://www.cnblogs.com/millen/archive/2010/01/18/1650423.html 失效情况分析: <> 单独的>,<,(有时会用 ...

  2. SQL SERVER 中is null 和 is not null 将会导致索引失效吗?

    其实本来这个问题没有什么好说的,今天优化的时候遇到一个SQL语句,因为比较有意思,所以我截取.简化了SQL语句,演示给大家看,如下所示 declare @bamboo_Code varchar(3); ...

  3. mysql索引失效

    在做项目的过程中,难免会遇到明明给mysql建立了索引,可是查询还是很缓慢的情况出现,下面我们来具体分析下这种情况出现的原因及解决方法   索引并不是时时都会生效的,比如以下几种情况,将导致索引失效: ...

  4. Oracle索引失效问题:WHERE C1='' OR C2 IN(SubQuery),并发请求时出现大量latch: cache buffers chains等待

    问题描述: 项目反馈某功能响应时间很长,高峰期时系统整体响应很慢... 获取相应的AWR,问题确实比较严重,latch: cache buffers chains等待,因为这些会话SQL执行时间太长, ...

  5. ORACLE索引失效原因归纳[转]

    1.隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误.   由于表的字段tu_mdn定义为varchar2(20),但在查询时把该字段作为number类型以where条件传给Orac ...

  6. oracle 使用ID关键字作列名导致索引失效

    oracle表空间变更导致主键索引失效,重建索引即可

  7. MYSQL索引失效的各种情形总结

    1) 没有查询条件,或者查询条件没有建立索引  2) 在查询条件上没有使用引导列  3) 查询的数量是大表的大部分,应该是30%以上.  4) 索引本身失效 5) 查询条件使用函数在索引列上,或者对索 ...

  8. oracle 索引失效原因及解决方法

    oracle 索引失效原因及解决方法 2010年11月26日 星期五 17:10 一.以下的方法会引起索引失效 ‍1,<>2,单独的>,<,(有时会用到,有时不会)3,like ...

  9. mysql索引之四(索引使用注意规则:索引失效--存在索引但不使用索引)

    但是如果是同样的sql如果在之前能够使用到索引,那么现在使用不到索引,以下几种主要情况: 1. 随着表的增长,where条件出来的数据太多,大于15%,使得索引失效(会导致CBO计算走索引花费大于走全 ...

  10. oracle 索引失效原因

    转自  http://www.cnblogs.com/orientsun/archive/2012/07/05/2577351.html Oracle 索引的目标是避免全表扫描,提高查询效率,但有些时 ...

随机推荐

  1. 关于Cocos2d-x中增加暂停按钮的步骤

    1.在GameScene.cpp的init方法中先定义一个里面放着可变换并在变换的时候会响应事件的MenuItem的Menu,这个Menu里面的可变换MenuItem又由两个小MenuItem组成,每 ...

  2. e685. 显示页面格式窗口

    The page format dialog allows the user to change the default page format values such as the orientat ...

  3. linux -- 查看Ubuntu命令行调用的文件

    which 如: 输入:which reboot 输出:/sbin/reboot 输入:which shutdown -h now 输出:/sbin/shutdown

  4. Oracle RAC:使用 NFS 共享存储时的 mount 选项 总结

    oracle rac 使用nfs作为共享存储时,mount的选项有 要求,不能随便设置 grid的要求:      rw,bg,hard,nointr,rsize=32768,wsize=32768, ...

  5. PureMVC--一款多平台MVC框架

    官网:http://puremvc.org/ 下载:https://github.com/PureMVC/puremvc-csharp-multicore-framework/tree/1.1.0 A ...

  6. XLua系统学习

    官方网站:https://github.com/Tencent/xLua 学习手册:http://manual.luaer.cn/ 技术博客: http://blog.csdn.net/column/ ...

  7. AsyncTask应用示例

    package com.example.testdemo; import java.io.ByteArrayOutputStream; import java.io.IOException; impo ...

  8. impala不能查询hive中新增加的表问题

         使用Cloudera Manager部署安装的CDH和Impala,Hive中新增加的表,impala中查询不到,其原因是/etc/impala/conf下面没有hadoop和hive相关的 ...

  9. 多进程模块:multiprocessing

    多进程: (1) 前面我们学习的多线程,其实算不上真正的多线程,即使你开了很多个线程,在同一时间内只能有一个CPU核数来处理一个线程(2) 在 python 中,多进程算得上是真正的多线程,假设你的C ...

  10. WAS创建虚拟主机和传输链

    一.配置虚拟主机 1.登录控制台