索引简介
CREATE TABLE test (
id integer,
name text
);
insert into test
select v,'val:'||v from generate_series(1, 10000000) v;
SELECT name FROM test WHERE id = 10000;
explain analyze
SELECT name FROM test WHERE id = 10000;
QUERY PLAN |
------------------------------------------------------------------------------------------------------------------------|
Gather (cost=1000.00..107137.70 rows=1 width=11) (actual time=50.266..12082.777 rows=1 loops=1) |
Workers Planned: 2 |
Workers Launched: 2 |
-> Parallel Seq Scan on test (cost=0.00..106137.60 rows=1 width=11) (actual time=7674.992..11553.964 rows=0 loops=3)|
Filter: (id = 10000) |
Rows Removed by Filter: 3333333 |
Planning Time: 16.480 ms |
Execution Time: 12093.016 ms |
CREATE INDEX test_id_index ON test (id);
explain analyze
SELECT name FROM test WHERE id = 10000;
QUERY PLAN |
---------------------------------------------------------------------------------------------------------------------|
Index Scan using test_id_index on test (cost=0.43..8.45 rows=1 width=11) (actual time=20.410..20.412 rows=1 loops=1)|
Index Cond: (id = 10000) |
Planning Time: 14.989 ms |
Execution Time: 20.521 ms |
索引类型
B-树索引
<
<=
=
>=
BETWEEN
IN
IS NULL
IS NOT NULL
col LIKE 'foo%'
col ~ '^foo'
SELECT col1, col2
FROM t
WHERE col1 BETWEEN 100 AND 200
ORDER BY col1;
哈希索引
CREATE INDEX index_name
ON table_name USING HASH (column_name);
GiST 索引
SELECT * FROM places ORDER BY location <-> point '(101,456)' LIMIT 10;
SP-GiST 索引
GIN 索引
BRIN 索引
创建索引
CREATE INDEX index_name ON table_name
[USING method]
(column_name [ASC | DESC] [NULLS FIRST | NULLS LAST]);
index_name 是索引的名称,table_name 是表的名称;
method 表示索引的类型,例如 btree、hash、gist、spgist、gin 或者 brin。默认为 btree;
column_name 是字段名,
ASC表示升序排序(默认值),DESC表示降序索引;NULLS FIRST和NULLS LAST表示索引中空值的排列顺序,升序索引时默认为NULLS LAST,降序索引时默认为NULLS FIRST。
CREATE INDEX test_name_index ON test (name);
explain analyze
SELECT * FROM test WHERE name IS NULL;
QUERY PLAN |
---------------------------------------------------------------------------------------------------------------------|
Index Scan using test_name_index on test (cost=0.43..5.77 rows=1 width=15) (actual time=0.036..0.037 rows=0 loops=1)|
Index Cond: (name IS NULL) |
Planning Time: 1.067 ms |
Execution Time: 0.048 ms |
唯一索引
CREATE UNIQUE INDEX index_name
ON table_name (column_name [ASC | DESC] [NULLS FIRST | NULLS LAST]);
多列索引
CREATE [UNIQUE] INDEX index_name ON table_name
[USING method]
(column1 [ASC | DESC] [NULLS FIRST | NULLS LAST], ...);
WHERE c1 = v1 and c2 = v2 and c3 = v3;
WHERE c1 = v1 and c2 = v2;
WHERE c1 = v1;
WHERE c2 = v2;
WHERE c3 = v3;
WHERE c2 = v2 and c3 = v3;
函数索引
CREATE [UNIQUE] INDEX index_name
ON table_name (expression);
explain analyze
SELECT * FROM test WHERE upper(name) ='VAL:10000';
QUERY PLAN |
---------------------------------------------------------------------------------------------------------------------------|
Gather (cost=1000.00..122556.19 rows=50001 width=15) (actual time=18.629..7310.422 rows=1 loops=1) |
Workers Planned: 2 |
Workers Launched: 2 |
-> Parallel Seq Scan on test (cost=0.00..116556.09 rows=20834 width=15) (actual time=4746.266..7171.452 rows=0 loops=3)|
Filter: (upper(name) = 'VAL:10000'::text) |
Rows Removed by Filter: 3333333 |
Planning Time: 0.100 ms |
Execution Time: 7310.444 ms |
drop index test_name_index;
create index test_name_index on test(upper(name));
explain analyze
SELECT * FROM test WHERE upper(name) ='VAL:10000';
QUERY PLAN |
-------------------------------------------------------------------------------------------------------------------------------|
Bitmap Heap Scan on test (cost=1159.93..57095.47 rows=50000 width=15) (actual time=17.046..17.047 rows=1 loops=1) |
Recheck Cond: (upper(name) = 'VAL:10000'::text) |
Heap Blocks: exact=1 |
-> Bitmap Index Scan on test_name_index (cost=0.00..1147.43 rows=50000 width=0) (actual time=17.032..17.032 rows=1 loops=1)|
Index Cond: (upper(name) = 'VAL:10000'::text) |
Planning Time: 1.985 ms |
Execution Time: 17.080 ms |
部分索引
create table orders(order_id int primary key, order_ts timestamp, finished boolean);
create index orders_unfinished_index
on orders (order_id)
where finished is not true;
explain analyze
select order_id
from orders
where finished is not true;
QUERY PLAN |
--------------------------------------------------------------------------------------------------------------------------------|
Bitmap Heap Scan on orders (cost=4.38..24.33 rows=995 width=4) (actual time=0.010..0.010 rows=0 loops=1) |
Recheck Cond: (finished IS NOT TRUE) |
-> Bitmap Index Scan on orders_unfinished_index (cost=0.00..4.13 rows=995 width=0) (actual time=0.004..0.004 rows=0 loops=1)|
Planning Time: 0.130 ms |
Execution Time: 0.049 ms |
覆盖索引
CREATE TABLE t (a int, b int, c int);
CREATE UNIQUE INDEX idx_t_ab ON t USING btree (a, b) INCLUDE (c);
explain analyze
select a, b, c
from t
where a = 100 and b = 200;
QUERY PLAN |
----------------------------------------------------------------------------------------------------------------|
Index Only Scan using idx_t_ab on t (cost=0.15..8.17 rows=1 width=12) (actual time=0.007..0.007 rows=0 loops=1)|
Index Cond: ((a = 100) AND (b = 200)) |
Heap Fetches: 0 |
Planning Time: 0.078 ms |
Execution Time: 0.021 ms |
查看索引
select * from pg_indexes where tablename = 'test';
schemaname|tablename|indexname |tablespace|indexdef |
----------|---------|---------------|----------|---------------------------------------------------------------------|
public |test |test_id_index | |CREATE INDEX test_id_index ON public.test USING btree (id) |
public |test |test_name_index| |CREATE INDEX test_name_index ON public.test USING btree (upper(name))|
维护索引
ALTER INDEX index_name RENAME TO new_name;
ALTER INDEX index_name SET TABLESPACE tablespace_name;
REINDEX [ ( VERBOSE ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } index_name;
删除索引
DROP INDEX index_name [ CASCADE | RESTRICT ];
DROP INDEX test_id_index, test_name_index;