我们都知道在数据库中不等于的查询是没有办法走索引的,所以一般使用<或>代替这样便可以走索引。那有没有办法让不等于查询走索引呢,方法是有的,只是这样性能并不见得比好。
例子:
建表及索引并插入测试数据:
bill=# create table tbl1(id int primary key, c1 int);
CREATE TABLE
bill=# create index idx_tbl1 on tbl1(c1);
CREATE INDEX
bill=# insert into tbl1 select generate_series(1,1000000), random()*10000;
INSERT 0 1000000
正常方法:
正常的查询我们知道肯定是没法走索引的。
bill=# explain (analyze,verbose,timing,costs,buffers) select * from tbl1 where c1 <> 1;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------
Seq Scan on bill.tbl1 (cost=0.00..16925.00 rows=999900 width=8) (actual time=0.012..129.578 rows=999897 loops=1)
Output: id, c1
Filter: (tbl1.c1 <> 1)
Rows Removed by Filter: 103
Buffers: shared hit=4425
Planning Time: 0.191 ms
Execution Time: 186.522 ms
(7 rows)
走索引的写法:
可以发现使用到了索引扫描,但是时间增长了一倍之多,甚至还用到了并行。
bill=# explain (analyze,verbose,timing,costs,buffers) select t1.* from tbl1 t1 left join tbl1 t2 on (t1.id=t2.id and t2.c1=1) where t2.* is null;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------
Gather (cost=1129.26..11314.68 rows=5000 width=8) (actual time=0.732..270.046 rows=999897 loops=1)
Output: t1.id, t1.c1
Workers Planned: 2
Workers Launched: 2
Buffers: shared hit=4829
-> Hash Left Join (cost=129.26..9814.68 rows=2083 width=8) (actual time=0.775..136.588 rows=333299 loops=3)
Output: t1.id, t1.c1
Inner Unique: true
Hash Cond: (t1.id = t2.id)
Filter: (t2.* IS NULL)
Rows Removed by Filter: 34
Buffers: shared hit=4829
Worker 0: actual time=0.925..191.707 rows=439294 loops=1
Buffers: shared hit=2094
Worker 1: actual time=1.078..189.059 rows=479026 loops=1
Buffers: shared hit=2270
-> Parallel Seq Scan on bill.tbl1 t1 (cost=0.00..8591.67 rows=416667 width=8) (actual time=0.016..45.266 rows=333333 loops=3)
Output: t1.id, t1.c1
Buffers: shared hit=4425
Worker 0: actual time=0.019..64.039 rows=439344 loops=1
Buffers: shared hit=1944
Worker 1: actual time=0.021..62.578 rows=479070 loops=1
Buffers: shared hit=2120
-> Hash (cost=128.01..128.01 rows=100 width=36) (actual time=0.628..0.628 rows=103 loops=3)
Output: t2.id, t2.*
Buckets: 1024 Batches: 1 Memory Usage: 15kB
Buffers: shared hit=314
Worker 0: actual time=0.755..0.755 rows=103 loops=1
Buffers: shared hit=105
Worker 1: actual time=0.827..0.828 rows=103 loops=1
Buffers: shared hit=105
-> Bitmap Heap Scan on bill.tbl1 t2 (cost=2.50..128.01 rows=100 width=36) (actual time=0.081..0.589 rows=103 loops=3)
Output: t2.id, t2.*
Recheck Cond: (t2.c1 = 1)
Heap Blocks: exact=101
Buffers: shared hit=314
Worker 0: actual time=0.092..0.718 rows=103 loops=1
Buffers: shared hit=105
Worker 1: actual time=0.101..0.773 rows=103 loops=1
Buffers: shared hit=105
-> Bitmap Index Scan on idx_tbl1 (cost=0.00..2.47 rows=100 width=0) (actual time=0.040..0.040 rows=103 loops=3)
Index Cond: (t2.c1 = 1)
Buffers: shared hit=11
Worker 0: actual time=0.051..0.051 rows=103 loops=1
Buffers: shared hit=4
Worker 1: actual time=0.052..0.052 rows=103 loops=1
Buffers: shared hit=4
Planning Time: 0.356 ms
Execution Time: 343.501 ms
(49 rows)