αα
αααα»ααα·ααααα Postgres αααααααααααΆαααΆααααααΆαααααααΆααααΆααα»αααααααααααααααα·αααααΆαααααααΆαααααα»ααα·αααααα (α α
ααΆ "α ααΆα")α Postgres αα·αααΆααααααΆαααΆααα
ααααααααααΆααααΆαα α αΎαααααΆαααααααα MVCC αααααΆαα±ααα’ααααααα
ααααΆαα½αααΉαααααααΆα
αααΎααα tuple ααΌα
ααααΆα ααΌα
αααα ααΆααΆαααΆααααααΆααααααΆααααΆαααααα»αααΆααααααΎα αα·ααααααΆαα·αα·ααααααααααααααααα·αααααΆα ααΎααααΈααΆαααααααααα·ααΈα
αααααΊααΆαααααΉααα½αα ααα½ααααααΆαααααααΎαααααα·αααααΆα αα·ααααααα’ααΆαααααΎααααΆαααα·αα·ααααα
α
αααΆαα αααα½αααααααα αΆαααΆααααααααααΎαααΆαααΎααΆααα·ααααααα
ααΆαααααΎααααΆααααααααααααααααααααα
ααΌααααα‘ααααΎαααααΎααα’αΆααααααΆαα’ααΈααααααααΆααα’αααααααΎααααΆααα’αααααα αα» customer
ααΆααα½ααααα½αα active
α αΎααααα½αααΊααΆααααα
pagila=# EXPLAIN SELECT email FROM customer WHERE active=0;
QUERY PLAN
-----------------------------------------------------------
Seq Scan on customer (cost=0.00..16.49 rows=15 width=32)
Filter: (active = 0)
(2 rows)
αααα½αβα α
βααααΆααβαααααβααΆααΆαβααα customer
. ααααααααΎααα·αα·αααααα
ααΎαα½ααα active
:
pagila=# CREATE INDEX idx_cust1 ON customer(active);
CREATE INDEX
pagila=# EXPLAIN SELECT email FROM customer WHERE active=0;
QUERY PLAN
-----------------------------------------------------------------------------
Index Scan using idx_cust1 on customer (cost=0.28..12.29 rows=15 width=32)
Index Cond: (active = 0)
(2 rows)
ααΆααΆααα½α ααΆααααααααΆαααααααααΆαααααααα
ααΆ "index scan
"α αααααΆααααααΆ Postgres ααΉααααααααααααααα "idx_cust1
" α αΎαβαααααΆααβααβααααβααΆαβαααααβααβαα½αβααΆααΆαβααΎααααΈβα’αΆαβαααααβααβαα½αβααβαααααβααα (αααα»αβααααΈβααα αα½αβαα email
) ααααααα½αααααΌαααΆαα
αααααααααααααααααααααααΌαααΆαααααΆααα αααα»α PostgreSQL 11 α αα½αααα’αα»ααααΆαα±ααα’ααααα½ααααα αΌααα½ααααααααααα½αα¬α αααΎααα αααα»ααα·αα·αααααααα½αααΆ - ααααααααααα½αααααααΌαααΆααααααΆαα»ααα αααα»αααααΆαααα·αααααααα·αα·ααααα
ααααα·αααΎααΎαααΆαααα’αααααααααααααΈαα»αααΆαααα α αΎααααααααααααα’ααΈααααα
ααΆααααα»ααα·αα·αααα ααα Postgres ααΉααα·αα
αΆαααΆα
ααααααααααΆααΆααααααααα email
. αααβααΎαβααΆβααΎβααΆβααΉαβααααΎαααΆαβα¬βα’ααα
pagila=# CREATE INDEX idx_cust2 ON customer(active) INCLUDE (email);
CREATE INDEX
pagila=# EXPLAIN SELECT email FROM customer WHERE active=0;
QUERY PLAN
----------------------------------------------------------------------------------
Index Only Scan using idx_cust2 on customer (cost=0.28..12.29 rows=15 width=32)
Index Cond: (active = 0)
(2 rows)
Β«Index Only Scan
' ααααΆααβααΎαβααΆβαααα½αβα₯α‘αΌαβαααβααααΌαααΆαβααβαα·αα·ααααβααα»ααααα αααβαα½αβαααααΆαβααΆααβααΆα I/O ααΎααααΈβα’αΆαβααΆααΆαα
ααααααααααααααααααααα αα α»ααααααααΆααααααΆααααααΎαααΎ B ααα»αααααα αααααΆαααΆαααΆααααααααα»αααααΈαααααΆααα·αααααααΉααααααααααΆαααΉααααααααΆαα
ααΆαααααΎααααΆαααααααααααααααα
αα·αα·αααααααααααααααααΎαα·αα·αααααααααα»ααααααα½αααααααα»αααΆααΆαααα»αααααα ααΆαααααΆαα»αααα ααααα·αα·αααα αα·αααααΎα±ααααΆααααααααΏαααΆααα»αα
α αΌααα·ααΆαααΆααΎαα ααααα½αααΆααααααΈα’αΆααααααΆαα’ααΈαααααααα’αα·αα·ααααααααΎααα αααα»αααααααΆααΈα αααααααΆα ααΆααααα»αααΉαααΆαααΌα αααα
SELECT c.email FROM customer c
JOIN address a ON c.address_id = a.address_id
WHERE a.district = 'California';
which has a query plan that involves scanning both the tables that are joined:
pagila=# EXPLAIN SELECT c.email FROM customer c
pagila-# JOIN address a ON c.address_id = a.address_id
pagila-# WHERE a.district = 'California';
QUERY PLAN
----------------------------------------------------------------------
Hash Join (cost=15.65..32.22 rows=9 width=32)
Hash Cond: (c.address_id = a.address_id)
-> Seq Scan on customer c (cost=0.00..14.99 rows=599 width=34)
-> Hash (cost=15.54..15.54 rows=9 width=4)
-> Seq Scan on address a (cost=0.00..15.54 rows=9 width=4)
Filter: (district = 'California'::text)
(6 rows)
α’αααΈααααααααααααααααααΆααΉααααααα±ααααΎα:
pagila=# CREATE INDEX idx_address1 ON address(district);
CREATE INDEX
pagila=# EXPLAIN SELECT c.email FROM customer c
pagila-# JOIN address a ON c.address_id = a.address_id
pagila-# WHERE a.district = 'California';
QUERY PLAN
---------------------------------------------------------------------------------------
Hash Join (cost=12.98..29.55 rows=9 width=32)
Hash Cond: (c.address_id = a.address_id)
-> Seq Scan on customer c (cost=0.00..14.99 rows=599 width=34)
-> Hash (cost=12.87..12.87 rows=9 width=4)
-> Bitmap Heap Scan on address a (cost=4.34..12.87 rows=9 width=4)
Recheck Cond: (district = 'California'::text)
-> Bitmap Index Scan on idx_address1 (cost=0.00..4.34 rows=9 width=0)
Index Cond: (district = 'California'::text)
(8 rows)
ααααα address
ααααΌαααΆααααα½ααααααΆααααααααααααααα idx_address1
α αΎααααααΆααααααΆαααααααααα address
.
αααααΆααααααΆαααα½αααΉαααΆαα α αΎαααααΌαααΆαααααΎα±αααααααΎα ααΎαα’αΆα
ααααΎαα·αα·αααααα½αααααα αααααααΎαα·αα·αααααααα½αααΆααααααααααΆαα’αΆααααααΆααα
αααα»ααααα»αα βCaliforniaβ
:
pagila=# CREATE INDEX idx_address2 ON address(address_id) WHERE district='California';
CREATE INDEX
pagila=# EXPLAIN SELECT c.email FROM customer c
pagila-# JOIN address a ON c.address_id = a.address_id
pagila-# WHERE a.district = 'California';
QUERY PLAN
------------------------------------------------------------------------------------------------
Hash Join (cost=12.38..28.96 rows=9 width=32)
Hash Cond: (c.address_id = a.address_id)
-> Seq Scan on customer c (cost=0.00..14.99 rows=599 width=34)
-> Hash (cost=12.27..12.27 rows=9 width=4)
-> Index Only Scan using idx_address2 on address a (cost=0.14..12.27 rows=9 width=4)
(5 rows)
α₯α‘αΌαααααααα½αααααΆααααα’αΆα idx_address2
αα·ααα·αααααα» address
.
ααΆαααααΎαα·αα·αααααα α»ααααα
αα½αβααβαα½αβα
ααα½αβαααβααααΌαβααααΎβαα·αα·ααααβα’αΆα
βααΉαβαα·αβααΆαβααααααβαα·ααααααβααΆαααααααΆαβααα αααααααα½αααααΌα
ααΆ jsonb
, arrays
ΠΈ tsvector
ααΆααααΆαααΆαα» α¬αααααα
αααΎαα ααααα·αααΎα’αααααααΌαααΆαααααΎαα·αα·αααααα½ααααααααα ααΆααααααΆα’αααααααΌααααααααααΆααααααααΈαα½αααα
αααα»ααα½αααααΆαααααα
α
αΌαααΎαααααΆααΆααααααααα
αααααΎαααααααααΆαααααααΆααα’αααααααΆαααΆαααΆααα
ααααΈααΆαααααααα·αααααααα αα» film
ααΆααα½αααα’ααααααα½αα α
ααΆ special_features
. ααααα·αααΎααΆαααααααΆα "αααααααααααααα·αα·ααα" ααα ααααα½αααααΆαααΆαα»ααΆα’αΆααα’ααααα Behind The Scenes
. ααΎααααΈαααααααααααααΆαααααααααααααΆααα’αα ααΎαααααΌαααααΎαααΎααα½αααΆααα’αααααααΆα "Behind The Scenes" αα
ααααααα ααΆαα½α αααααα’αΆαα special_features
:
SELECT title FROM film WHERE special_features @> '{"Behind The Scenes"}';
ααααα·ααααα·αααααα»α @>
αα·αα·αααααΎαααΆααΎαααααααΆαααααΆαααΊααΆααααααααααααααααΆααααααα
ααααΎαα»αααααααα
pagila=# EXPLAIN SELECT title FROM film
pagila-# WHERE special_features @> '{"Behind The Scenes"}';
QUERY PLAN
-----------------------------------------------------------------
Seq Scan on film (cost=0.00..67.50 rows=5 width=15)
Filter: (special_features @> '{"Behind The Scenes"}'::text[])
(2 rows)
αααααααΎαα»αααΆααααααααααααα αααΆα 67 α
αααααΎαααΆααΎααααααααα B-tree ααααααΆαα½αααΎαααα
pagila=# CREATE INDEX idx_film1 ON film(special_features);
CREATE INDEX
pagila=# EXPLAIN SELECT title FROM film
pagila-# WHERE special_features @> '{"Behind The Scenes"}';
QUERY PLAN
-----------------------------------------------------------------
Seq Scan on film (cost=0.00..67.50 rows=5 width=15)
Filter: (special_features @> '{"Behind The Scenes"}'::text[])
(2 rows)
αα·αα·αααααα·αααααΌαααΆααααα·αααΌααααΈααα ααααααααα B-tree αα·αααΉαααΈα’αααα·ααΆαααααΆαα»ααΈαα½αααα αααα»αααααααααααΆαααααΎαα·αα·ααααααα
ααΎαααααΌαααΆαααααααααα GIN α
pagila=# CREATE INDEX idx_film2 ON film USING GIN(special_features);
CREATE INDEX
pagila=# EXPLAIN SELECT title FROM film
pagila-# WHERE special_features @> '{"Behind The Scenes"}';
QUERY PLAN
---------------------------------------------------------------------------
Bitmap Heap Scan on film (cost=8.04..23.58 rows=5 width=15)
Recheck Cond: (special_features @> '{"Behind The Scenes"}'::text[])
-> Bitmap Index Scan on idx_film2 (cost=0.00..8.04 rows=5 width=0)
Index Cond: (special_features @> '{"Behind The Scenes"}'::text[])
(4 rows)
ααααααααα GIN ααΆααααααΆαααΌααααααΈααααααααα½ααααααΆααααΉαααααααααΆαααΆαα»αααααΆαααααΎαα·αα·αααα ααααααααΆαα±ααααΆαααΆαα αααΆαααΎαααααααααα½ααααααΆαα αααΎαααΆαααΆαααααααΆαα
αααα αΆαααα·αα·αααααααα½α
αααααααααβαααα»αβααΆαβαααβααααΆ α αΎαβαααβααααβαααααααααβααααΈβα’αΆα
βααΆαβαα·αααααβααΌα
βααααΆβααΉαβαααααααααβαα½αβαααα»αβα
ααααβαααααααααβαα»ααα α’αααα’αΆα
ααααΎαα·αααααΆαααΆααΆα‘α»αααΎααααΈααα½αααΆααα·ααααα SQL αααα’αΆα
α’αΆαααΆαααααααα»ααααααα·αα·ααααα pg_indexes
. α’αααααα’αΆα
ααααααααα·αααααααΌα
ααααΆααΆααααΆαααΆααααα½ααααααα
SELECT array_agg(indexname) AS indexes, replace(indexdef, indexname, '') AS defn
FROM pg_indexes
GROUP BY defn
HAVING count(*) > 1;
And hereβs the result when run on the stock pagila database:
pagila=# SELECT array_agg(indexname) AS indexes, replace(indexdef, indexname, '') AS defn
pagila-# FROM pg_indexes
pagila-# GROUP BY defn
pagila-# HAVING count(*) > 1;
indexes | defn
------------------------------------------------------------------------+------------------------------------------------------------------
{payment_p2017_01_customer_id_idx,idx_fk_payment_p2017_01_customer_id} | CREATE INDEX ON public.payment_p2017_01 USING btree (customer_id
{payment_p2017_02_customer_id_idx,idx_fk_payment_p2017_02_customer_id} | CREATE INDEX ON public.payment_p2017_02 USING btree (customer_id
{payment_p2017_03_customer_id_idx,idx_fk_payment_p2017_03_customer_id} | CREATE INDEX ON public.payment_p2017_03 USING btree (customer_id
{idx_fk_payment_p2017_04_customer_id,payment_p2017_04_customer_id_idx} | CREATE INDEX ON public.payment_p2017_04 USING btree (customer_id
{payment_p2017_05_customer_id_idx,idx_fk_payment_p2017_05_customer_id} | CREATE INDEX ON public.payment_p2017_05 USING btree (customer_id
{idx_fk_payment_p2017_06_customer_id,payment_p2017_06_customer_id_idx} | CREATE INDEX ON public.payment_p2017_06 USING btree (customer_id
(6 rows)
Superset Index
ααΆα’αΆα ααΎαα‘αΎααααα’ααααααα ααααααα·αα·ααααααΆα αααΎα ααααα½ααααα»αα αααααααααααΎαα·αα·αααααααα»αααΎααααα½ααααααααααΎαα·αα·ααααααααααααα αααα’αΆα α¬αααα ααααΆαα·αα ααααΆα - αααα»αααΆαααΎα’αΆα αααααΆαα±ααααΆαααΆαααααααααααΆαααααα·αα·αααα αααααΆααΆαααα’ ααα»ααααααΆαααα ααααΆααααΌαααΆαααα ααααα»αα αααΎαααα α¬αααα½αααααααα»αααΆαααΎααΆαααααααααΎα±αααααααΎααα·αααααΌαααΆαααααΎααααΆαααααααα
ααααα·αααΎα’αααααααΌαααΆαααααααααααααα·αααααα·ααααααααα·αα·αααααααααα α’αααα’αΆα
α
αΆααααααΎαααΆαα½α pg_catalog
.
αα·αα·ααααααααα·αααααΎ
αααααΆααααααα·ααΈαααααααΎααΌαααααΆααα·αααααααα·αααααα ααΌα
ααααααΌαααααΎαααα½αααααα½αααααααΎα αααααααααβαααβααΆαβααααααβαα»αβα’αΆα
βααΉαβαα·αβααααΌαβααΆαβααααΎβαααβαααα½αβααΆβαα½αβαααβααα ααΆαααααααααααααααααααααΌαααΆαααααα ααΆααααΌαααΆααααααΆαααααα’αααααααααααααααα·αα· αα·ααα
αααα»ααα·αααααΆαααΆααΆα‘α»ααααααααα pg_stat_user_indexes
α’αααα’αΆα
ααΎαααααα idx_scan
αααβααΆβααΆαβααΆααβααααααα ααΆαααΆαααΆααααααααααααα»ααααααααα½α (αα·ααΆααα½ααα) ααΉαααααααααα·αααα’α’αααΈαααααααααααΆαα½αααααα·αααααΌαααΆαααααααΎααααΆαα α αΎαα’αΆα
ααααΌαααΆααααααΆααα
αααααΊααΆαααα½αααΎααααΈααα½αααΆαα
ααα½αααααααα
αα
α»αααααααααααααααααααΆααα’αααα
αααα»ααααααααΆααα βpublicβ
:
SELECT relname, indexrelname, idx_scan
FROM pg_catalog.pg_stat_user_indexes
WHERE schemaname = 'public';
with output like this:
pagila=# SELECT relname, indexrelname, idx_scan
pagila-# FROM pg_catalog.pg_stat_user_indexes
pagila-# WHERE schemaname = 'public'
pagila-# LIMIT 10;
relname | indexrelname | idx_scan
---------------+--------------------+----------
customer | customer_pkey | 32093
actor | actor_pkey | 5462
address | address_pkey | 660
category | category_pkey | 1000
city | city_pkey | 609
country | country_pkey | 604
film_actor | film_actor_pkey | 0
film_category | film_category_pkey | 0
film | film_pkey | 11043
inventory | inventory_pkey | 16048
(10 rows)
ααΆααααααΎααα·αα·ααααα‘αΎααα·αααΆαα½αααΉαααΆαα αΆαααααα·α ααΆα
ααΆααΏαααααααααααααααΌααααααΎαα‘αΎααα·α α§ααΆα ααααα ααααααααΆα αΎαααα α αΎαααΆαααααΆαααΆα‘αΎααα·αα’αΆα αααααΎαααααΏααααααα αααααααααααα’αΆα ααΌα αααααα ααΆαααααΆααααααΌααααΆαααΆαααααααα·αα·ααααααα’αΆα αααααΌαα±ααααΆαααΆααααΆαααΆα‘αΎααα·ααααααα
ααΎαααΆααααααΎααα·αα·αααααααΆαααΆα‘αα
αα αααα»α PostgreSQL 11 ααΆααααααΎαααααααααα B-Tree ααΊααααααααΆα ααΎααααΈαααααΎαααααΏαααααΎαααΆααααααΎα αααααααααΆαααΆα‘ααααΆα αααΎαα’αΆα ααααΌαααΆαααααΎα ααααααΆαααΆααααα ααααΌαααααΆααααΆαααααΎαααααΆαααααααα ααΆααααααααααΆαααααααααΌαααΆαααααααααΆαααααΉαααααΌαα
SET max_parallel_workers = 32;
SET max_parallel_maintenance_workers = 16;
αααααααααΆαααΎαααΊααΌα
αααα ααΆαα§ααααααα· αααααΆααααααα½αααααΎαα‘αΎα αα½αααΆαα½αααΉαα
ααα½αααααΌαααααΎαααΆαα α’αΆααααααααα
αααα»α
ααΆααααααΎααα·αα·ααααααααααΆαααααα
α’αααα’αΆα
αααααΎααα·αα·αααααααα»αααααααΆαααααααααααααΎαααααΎα CONCURRENTLY
ααΆααααααααΆ CREATE INDEX
:
pagila=# CREATE INDEX CONCURRENTLY idx_address1 ON address(district);
CREATE INDEX
ααααΎαααΆααααααΎααα·αα·ααααααααα»αααΈααααααΆ αααααΆαα·ααααααΌαα±ααααΆαααΆαα αΆααααααα ααΎαα» α αΎαααΌα ααααααΆαα·αααΆααΆααααααα·ααααα·ααΆααααααααα αααααΆααα·αααα ααΆααααΌαααΆααααααααΆ αα·αααααΎααααΆααααααΆαααΆααααα αααΎαα
Postgres αααααααΌαααΆαααααααααΆα
αααΎααααααΆααααΆααααααΎααα·αα·αααα αα·ααα·ααΈααΎααααΈαααααααΆαααααΈαα·αααααΆαα½α ααααΌα
ααΆαα·ααΈααΎααααΈαααααααααααΌαααααΆααα·αααααααααα»αααααΈααααααααα·ααΈααααα’αααααΈαα
ααααΎαααααΆααα ααΎααααααΉαααΆαααααΉαααΆαααααααΉααα½αα’αααα±ααααα½αααΆααααα½αααααα’ααααααΆαααΆαααα αα α αΎαααΌαααααΆααα·ααααααααααα’ααααα½α
ααΆααααΎααααΈααααΎααΆαααααααΆαα
ααααα: www.habr.com