ื ื™ืฆืŸ ืึทืœืข ื“ื™ ืงื™ื™ืคึผืึทื‘ื™ืœืึทื˜ื™ื– ืคื•ืŸ ื™ื ื“ืขืงืกื™ื– ืื™ืŸ PostgreSQL

ื ื™ืฆืŸ ืึทืœืข ื“ื™ ืงื™ื™ืคึผืึทื‘ื™ืœืึทื˜ื™ื– ืคื•ืŸ ื™ื ื“ืขืงืกื™ื– ืื™ืŸ PostgreSQL
ืื™ืŸ ื“ื™ Postgres ื•ื•ืขืœื˜, ื™ื ื“ืขืงืกื™ื– ื–ืขื ืขืŸ ืงืจื™ื˜ื™ืฉ ืฆื• ื™ืคื™ืฉืึทื ื˜ืœื™ ื ืึทื•ื•ืึทื’ื™ื™ื˜ื™ื ื’ ื“ื™ ื“ืึทื˜ืึทื‘ื™ื™ืก ืกื˜ืึธืจื™ื“ื–ืฉ (ื’ืขืจื•ืคืŸ ื“ื™ ืงื•ืคึผืข). Postgres ืฉื˜ื™ืฆื˜ ื ื™ืฉื˜ ืงืœืึทืกื˜ืขืจื™ื ื’ ืคึฟืึทืจ ืขืก, ืื•ืŸ ื“ื™ MVCC ืึทืจืงืึทื˜ืขืงื˜ืฉืขืจ ื’ืขืคึฟื™ืจื˜ ืื™ืจ ืฆื• ืขื ื“ื™ืงืŸ ืžื™ื˜ ืคื™ืœืข ื•ื•ืขืจืกื™ืขืก ืคื•ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ื˜ื•ืคึผืœืข. ื“ืขืจื™ื‘ืขืจ, ืขืก ืื™ื– ื–ื™ื™ืขืจ ื•ื•ื™ื›ื˜ื™ืง ืฆื• ืงืขื ืขืŸ ืฆื• ืฉืึทืคึฟืŸ ืื•ืŸ ื˜ื™ื™ึทื ืขืŸ ืขืคืขืงื˜ื™ื•ื• ื™ื ื“ืขืงืกื™ื– ืฆื• ืฉื˜ื™ืฆืŸ ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื–.

ืื™ืš ื‘ืจืขื ื’ืขืŸ ืฆื• ื“ื™ื™ืŸ ื•ืคืžืขืจืงื–ืึทืžืงื™ื™ึทื˜ ืขื˜ืœืขื›ืข ืขืฆื•ืช ืคึฟืึทืจ ืึธืคึผื˜ื™ืžื™ื–ื™ื ื’ ืื•ืŸ ื™ืžืคึผืจื•ื•ื•ื™ื ื’ ื“ื™ ื ื•ืฆืŸ ืคื•ืŸ ื™ื ื“ืขืงืกื™ื–.

ื‘ืึทืžืขืจืงื•ื ื’: ื“ื™ ืงื•ื•ื™ืจื™ื– ื’ืขื•ื•ื™ื–ืŸ ืื•ื ื˜ืŸ ืึทืจื‘ืขื˜ ืื•ื™ืฃ ืึทื ืžืึธื“ื™ืคื™ืขื“ ืคึผืึทื’ื™ืœืึท ื“ืึทื˜ืึทื‘ื™ื™ืก ืžื•ืกื˜ืขืจ.

ื ื™ืฆืŸ ืงืึทื•ื•ืขืจื™ื ื’ ื™ื ื“ืขืงืกื™ื–

ื–ืืœ ืก ืงื•ืง ืื™ืŸ ืึท ื‘ืงืฉื” ืฆื• ืฆื•ืจื™ืงืงืจื™ื’ืŸ E- ื‘ืจื™ื•ื• ื•ื•ืขื ื“ื˜ ืคึฟืึทืจ ื™ื ืึทืงื˜ื™ื•ื• ื™ื•ื–ืขืจื–. ืื™ืŸ ื“ื™ ื˜ื™ืฉ 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 ื™ื ื˜ืจืึธื•ื“ื•ืกื˜ ืงืึทื•ื•ืขืจื™ื ื’ ื™ื ื“ืขืงืกื™ื–. ื–ื™ื™ ืœืึธื–ืŸ ืื™ืจ ืฆื• ืึทืจื™ื™ึทื ื ืขืžืขืŸ ืื™ื™ื ืขืจ ืึธื“ืขืจ ืžืขืจ ื ืึธืš ืฉืคืืœื˜ืŸ ืื™ืŸ ื“ืขืจ ืื™ื ื“ืขืงืก ื–ื™ืš - ื–ื™ื™ืขืจ ื•ื•ืึทืœื•ืขืก ื–ืขื ืขืŸ ืกื˜ืึธืจื“ ืื™ืŸ ื“ื™ ืื™ื ื“ืขืงืก ื“ืึทื˜ืŸ ืงืจืึธื.

ืื•ื™ื‘ ืžื™ืจ ื’ืขื•ื•ื™ื™ื ื˜ ื“ืขื ืฉื˜ืจื™ืš ืื•ืŸ ืฆื•ื’ืขื’ืขื‘ืŸ ื“ื™ E- ื‘ืจื™ื•ื• ื•ื•ืขืจื˜ ื™ืŸ ื“ืขืจ ืื™ื ื“ืขืงืก, 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 ืฆื• ืœื™ื™ืขื ืขืŸ ื“ื™ ืงื•ืคึผืข ืคื•ืŸ โ€‹โ€‹ื“ื™ ื˜ื™ืฉ.

ื”ื™ื™ึทื ื˜, ืงืึทื•ื•ืขืจื™ื ื’ ื™ื ื“ืขืงืกื™ื– ื–ืขื ืขืŸ ื‘ืœื•ื™ื– ื‘ื ื™ืžืฆื ืคึฟืึทืจ ื‘-ื‘ื™ื™ืžืขืจ. ืึธื‘ืขืจ, ืื™ืŸ ื“ืขื ืคืึทืœ, ื“ื™ ื•ื™ืฉืึทืœื˜ ืžื™ ื•ื•ืขื˜ ื–ื™ื™ืŸ ื”ืขื›ืขืจ.

ื ื™ืฆืŸ ืคึผืึทืจื˜ื™ื™ื™ืฉ ื™ื ื“ืขืงืกื™ื–

ื˜ื™ื™ืœ ื™ื ื“ืขืงืกื™ื– ืื™ื ื“ืขืงืก ื‘ืœื•ื™ื– ืึท ืกืึทื‘ืกืขื˜ ืคื•ืŸ ื“ื™ ืจืึธื•ื– ืคื•ืŸ ื“ื™ ื˜ื™ืฉ. ื“ืึธืก ืึทืœืึทื•ื– ืื™ืจ ืฆื• ืจืึทื˜ืขื•ื•ืขืŸ ื“ื™ ืื™ื ื“ืขืงืก ื’ืจื™ื™ืก ืื•ืŸ ื“ื•ืจื›ืคื™ืจืŸ ืกืงืึทื ื– ืคืึทืกื˜ืขืจ.

ื–ืืœ ืก ื–ืึธื’ืŸ ืžื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ื‘ืึทืงื•ืžืขืŸ ืึท ืจืฉื™ืžื” ืคื•ืŸ E- ื‘ืจื™ื•ื• ืึทื“ืจืขืกืขืก ืคึฟืึทืจ ืื•ื ื“ื–ืขืจ ืงืึทืกื˜ืึทืžืขืจื– ืื™ืŸ ืงืึทืœื™ืคืึธืจื ื™ืึท. ื“ื™ ื‘ืงืฉื” ื•ื•ืขื˜ ื–ื™ื™ืŸ ื•ื•ื™ ื“ืึธืก:

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. ืฆื• ื–ื•ื›ืŸ ืคึฟืึทืจ ืึทืœืข ืึทื–ืึท ืคื™ืœืžืก, ืžื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืื•ื™ืกืงืœื™ื™ึทื‘ืŸ ืึทืœืข ืจืึธื•ื– ืžื™ื˜ "ื”ื™ื ื˜ืขืจ ื“ื™ ืกื™ื ื–" ื‘ื™ื™ึท ืงื™ื™ืŸ ืžืขื ื’ืข ื•ื•ืึทืœื•ืขืก 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.

ืœืึธืžื™ืจ ื–ืขืŸ ืื•ื™ื‘ ืึท ืจืขื’ื•ืœืขืจ ื‘-ื‘ื•ื™ื ืื™ื ื“ืขืงืก ื•ื•ืขื˜ ื”ืขืœืคึฟืŸ ืื•ื ื“ื–:

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)

ื“ืขืจ ืื™ื ื“ืขืงืก ืื™ื– ืืคื™ืœื• ื ื™ืฉื˜ ื‘ืื˜ืจืื›ื˜ ื’ืขื•ื•ืืจืŸ. ื“ื™ ื‘-ื‘ื•ื™ื ืื™ื ื“ืขืงืก ื”ืื˜ ืงื™ื™ืŸ ื’ืขื“ืึทื ืง ื•ื•ืขื’ืŸ ื“ื™ ืขืงื–ื™ืกื˜ืขื ืฅ ืคื•ืŸ ื™ื—ื™ื“ ืขืœืขืžืขื ื˜ืŸ ืื™ืŸ ื“ื™ ื•ื•ืึทืœื•ืขืก ืขืก ื™ื ื“ืขืงืกื™ื–.

ืžื™ืจ ื“ืึทืจืคึฟืŸ ืึท 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 ืื™ื ื“ืขืงืก ืฉื˜ื™ืฆื˜ ืžืึทืคึผื™ื ื’ ื™ื—ื™ื“ ื•ื•ืึทืœื•ืขืก ืฆื• ื™ื ื“ืขืงืกื˜ ืงืึทืžืคึผืึทื–ืึทื˜ ื•ื•ืึทืœื•ืขืก, ืจื™ื–ืึทืœื˜ื™ื ื’ ืื™ืŸ ืžืขืจ ื•ื•ื™ ื”ืึทืœื‘ ื“ื™ ืคึผืจื™ื™ึทื– ืคื•ืŸ ื“ื™ ืึธื ืคึฟืจืขื’ ืคึผืœืึทืŸ.

ื‘ืึทืงื•ืžืขืŸ ื‘ืึทืคืจื™ื™ึทืขืŸ ืคื•ืŸ ื“ื•ืคึผืœื™ืงืึทื˜ ื™ื ื“ืขืงืกื™ื–

ื™ื ื“ืขืงืกื™ื– ืึทืงื™ื•ืžื™ืึทืœื™ื™ื˜ ืžื™ื˜ ืฆื™ื™ึทื˜, ืื•ืŸ ืžืืœ ืึท ื ื™ื™ึท ืื™ื ื“ืขืงืก ืงืขืŸ ืึทื ื˜ื”ืึทืœื˜ืŸ ื“ื™ ื–ืขืœื‘ืข ื“ืขืคึฟื™ื ื™ืฆื™ืข ื•ื•ื™ ืื™ื™ื ืขืจ ืคื•ืŸ ื“ื™ ืคืจื™ืขืจื“ื™ืงืข ืึธื ืขืก. ืื™ืจ ืงืขื ืขืŸ ื ื•ืฆืŸ ื“ื™ ืงืึทื˜ืึทืœืึธื’ ืžื™ื™ื ื•ื ื’ ืฆื• ืงืจื™ื’ืŸ ืžืขื ื˜ืฉ-ืœื™ื™ื ืขื•ื•ื“ื™ืง ืกืงืœ ืื™ื ื“ืขืงืก ื–ื•ืš 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)

ืกื•ืคึผืขืจืกืขื˜ ื™ื ื“ืขืงืกื™ื–

ืขืก ืงืขืŸ ืคึผืึทืกื™ืจืŸ ืึทื– ืื™ืจ ืึธื ืงืœื™ื™ึทื‘ืŸ ืคื™ืœืข ื™ื ื“ืขืงืกื™ื–, ืื™ื™ื ืขืจ ืคื•ืŸ ื•ื•ืึธืก ื™ื ื“ืขืงืกื™ื– ืึท ืกื•ืคึผืขืจืกืขื˜ ืคื•ืŸ ืฉืคืืœื˜ืŸ ื•ื•ืึธืก ืื ื“ืขืจืข ื™ื ื“ืขืงืกื™ื–. ื“ืึธืก ืงืขืŸ ืึธื“ืขืจ ืงืขืŸ ื ื™ืฉื˜ ื–ื™ื™ืŸ ื“ื™ื–ื™ื™ืขืจืึทื‘ืึทืœ - ืึท ืกื•ืคึผืขืจืกืขื˜ ืงืขืŸ ืจืขื–ื•ืœื˜ืึทื˜ ืื™ืŸ ืึทืŸ ืื™ื ื“ืขืงืก-ื‘ืœื•ื™ื– ื™ื‘ืขืจืงื•ืงืŸ, ื•ื•ืึธืก ืื™ื– ื’ื•ื˜, ืึธื‘ืขืจ ืขืก ืงืขืŸ ื ืขืžืขืŸ ืฆื• ืคื™ืœ ืคึผืœืึทืฅ, ืึธื“ืขืจ ื“ื™ ืึธื ืคึฟืจืขื’ ื•ื•ืึธืก ื“ื™ ืกื•ืคึผืขืจืกืขื˜ ืื™ื– ื‘ื“ืขื” ืฆื• ืึทืคึผื˜ืึทืžื™ื™ื– ืื™ื– ื ื™ื˜ ืžืขืจ ืื™ืŸ ื ื•ืฆืŸ.

ืื•ื™ื‘ ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืึธื˜ืึทืžื™ื™ื˜ ื“ื™ ื“ืขืคึฟื™ื ื™ืฆื™ืข ืคื•ืŸ โ€‹โ€‹ืึทื–ืึท ื™ื ื“ืขืงืกื™ื–, ืื™ืจ ืงืขื ืขืŸ ืึธื ื”ื™ื™ื‘ืŸ ืžื™ื˜ pg_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

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’