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, ‘2‘::double precision) = ‘1‘::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 = ‘1‘;
                                                           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 = ‘1‘::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
时间: 2024-10-24 03:49:38

postgresql----索引失效的相关文章

MySQL高级 之 索引失效与优化详解

案例所用的表结构.索引.与数据如下:   索引失效与优化 1.全值匹配我最爱 2.最佳左前缀法则(带头索引不能死,中间索引不能断) 如果索引了多个列,要遵守最佳左前缀法则.指的是查询从索引的最左前列开始 并且 不跳过索引中的列. 正确的示例参考上图. 错误的示例: 带头索引死:  中间索引断(带头索引生效,其他索引失效):  3.不要在索引上做任何操作(计算.函数.自动/手动类型转换),不然会导致索引失效而转向全表扫描 4.mysql存储引擎不能继续使用索引中范围条件(bettween.<.>

Oracle 分区表中索引失效

当对分区表进行 一些操作时,会造成索引失效. 当有truncate/drop/exchange 操作分区  时全局索引 会失效. exchange 的临时表没有索引,或者有索引,没有用including indexes的关键字,会导致局部的索引失效,就是某个分区失效重建局部索引只能用alter index local_idx rebuild partition p1这样的方式 分区表SPLIT的时候,如果MAX区中已经有记录了,这个时候SPLIT就会导致有记录的新增分区的局部索引失效! 查寻某个

主键查询值,int与字符串类型混用导致索引失效

select * from user where id in (5230,'45') *************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: user         type: ALLpossible_keys: PRIMARY          key: NULL      key_len: NULL          r

sql server数据库中索引失效的问题讨论

有关于数据库中索引失效的问题,网上也有相关的讨论.不过他们是针对oracle数据库进行讨论的.那么在sql server数据库中索引什么时候 会失效呢.总结了一下,不过我没有经过测试.没测试就没有发言权,这里仅供自己参考. 首先,所谓失效.并不真的就是这个索引被删除了.而是在这些情况下,DBMS不会检索索引列表了.执行速度和没有这个索引时的速度一样. 但是再执行另外的一条语句.同样索引可以正常起作用.所以索引的失效是针对某条sql语句的,而不是针对索引本身的.那么在哪些情况下, 确切的说是在哪类

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

原文:SQL SERVER 中is null 和 is not null 将会导致索引失效吗? 其实本来这个问题没有什么好说的,今天优化的时候遇到一个SQL语句,因为比较有意思,所以我截取.简化了SQL语句,演示给大家看,如下所示 declare @bamboo_Code varchar(3);   set @bamboo_Code='-01';     SELECT DISTINCT yarn_lot FROM   dbo.rsjob WITH ( nolock ) WHERE  RIGHT(

Oracle数据库索引使用及索引失效总结

容易引起oracle索引失效的原因很多: 1.在索引列上使用函数.如SUBSTR,DECODE,INSTR等,对索引列进行运算.需要建立函数索引就可以解决了. 2.新建的表还没来得及生成统计信息,分析一下就好了 3.基于cost的成本分析,访问的表过小,使用全表扫描的消耗小于使用索引. 4.使用<>.not in .not exist,对于这三种情况大多数情况下认为结果集很大,一般大于5%-15%就不走索引而走FTS. 5.单独的>.<. 6.like "%_"

MySQL表字段字符集不同导致的索引失效问题

1. 概述 昨天在一位同学的MySQL机器上面发现了这样一个问题,MySQL两张表做left join时,执行计划里面显示有一张表使用了全表扫描,扫描全表近100万行记录,大并发的这样的SQL过来数据库变得几乎不可用了,今天和大家一起分享下这个问题的原因及解决办法,希望可以帮助大家更好的学习MySQL数据库,一起来看看吧.MySQL版本为官方5.7.12. 2. 问题重现 首先,表结构和表记录如下: mysql> show create table t1\G ******************

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

1) 没有查询条件,或者查询条件没有建立索引 2) 在查询条件上没有使用引导列 3) 查询的数量是大表的大部分,应该是30%以上. 4) 索引本身失效 5) 查询条件使用函数在索引列上,或者对索引列进行运算,运算包括(+,-,*,/,! 等) 错误的例子:select * from test where id-1=9; 正确的例子:select * from test where id=10; 6) 对小表查询 7) 提示不使用索引 8) 统计数据不真实 9) CBO计算走索引花费过大的情况.其

oracle 索引失效原因

摘自网络http://blog.chinaunix.net/uid-23622436-id-3184356.html oracle 索引失效的原因 分类: Oracle 1) 没有查询条件,或者查询条件没有建立索引 2) 在查询条件上没有使用引导列 3) 查询的数量是大表的大部分,应该是30%以上. 4) 索引本身失效 5) 查询条件使用函数在索引列上(见12) 6) 对小表查询 7) 提示不使用索引 8) 统计数据不真实 9) CBO计算走索引花费过大的情况.其实也包含了上面的情况,这里指的是

SQL查询:『索引失效问题』

1.IN操作符 用IN操作符写出来的SQL直观简单.易于理解.但是在where条件中使用IN操作符是低效的.例如下面这条查询语句: SELECT * FROM tab_a WHERE id IN( SELECT a_id FROM tab_b); 你认为它会怎么执行呢?先从tab_a表中遍历数据,然后拿每行数据的id字段去tab_b表中去查找,只要找到就把这行纳入查询结果. 大错特错!事实上,RDBMS会先执行第4行的子查询,把查出的数据保存到一张临时表中,再执行主查询,利用临时表中的数据去核对