ИзползванС Π½Π° всички Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈ Π½Π° индСкситС Π² PostgreSQL

ИзползванС Π½Π° всички Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈ Π½Π° индСкситС Π² PostgreSQL
Π’ свСта Π½Π° Postgres индСкситС са ΠΈΠ·ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ Π²Π°ΠΆΠ½ΠΈ Π·Π° Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½Π°Ρ‚Π° навигация Π² Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅Ρ‚ΠΎ Π½Π° Π±Π°Π·Π°Ρ‚Π° Π΄Π°Π½Π½ΠΈ (Π½Π°Ρ€Π΅Ρ‡Π΅Π½ΠΎ β€žΠΊΡƒΡ‡Π°β€œ, heap). Postgres Π½Π΅ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ° ΠΊΠ»ΡŠΡΡ‚Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π·Π° Π½Π΅Π³ΠΎ, Π° Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°Ρ‚Π° MVCC Π²ΠΎΠ΄ΠΈ Π΄ΠΎ Π½Π°Ρ‚Ρ€ΡƒΠΏΠ²Π°Π½Π΅ Π½Π° ΠΌΠ½ΠΎΠ³ΠΎ вСрсии Π½Π° Π΅Π΄ΠΈΠ½ ΠΈ ΡΡŠΡ‰ΠΈ ΠΊΠΎΡ€Ρ‚Π΅ΠΆ. Π—Π°Ρ‚ΠΎΠ²Π° Π΅ ΠΈΠ·ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ Π²Π°ΠΆΠ½ΠΎ Π΄Π° Π·Π½Π°Π΅Ρ‚Π΅ ΠΊΠ°ΠΊ Π΄Π° ΡΡŠΠ·Π΄Π°Π²Π°Ρ‚Π΅ ΠΈ ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ°Ρ‚Π΅ Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΈ индСкси Π·Π° ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π½Π° прилоТСния.

ΠŸΡ€Π΅Π΄Π»Π°Π³Π°ΠΌ Π²ΠΈ няколко ΡΡŠΠ²Π΅Ρ‚Π° Π·Π° оптимизация ΠΈ подобряванС Π½Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° индСкситС.

Π—Π°Π±Π΅Π»Π΅ΠΆΠΊΠ°: ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΈΡ‚Π΅ ΠΏΠΎ-Π΄ΠΎΠ»Ρƒ заявки работят Π½Π° нСмодифицирания ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π½Π° Π±Π°Π·Π°Ρ‚Π° Π΄Π°Π½Π½ΠΈ pagila.

ИзползванС Π½Π° ΠΏΠΎΠΊΡ€ΠΈΠ²Π°Ρ‰ΠΈ индСкси (Covering Indexes)

НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ заявка Π·Π° ΠΈΠ·Π²Π»ΠΈΡ‡Π°Π½Π΅ Π½Π° ΠΈΠΌΠ΅ΠΉΠ» адрСси Π½Π° Π½Π΅Π°ΠΊΡ‚ΠΈΠ²Π½ΠΈ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΠΈ. Π’ Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° 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β€œ, Π° слСд Ρ‚ΠΎΠ²Π° Ρ‰Π΅ ΠΏΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠΈ Π΄Π° Ρ‚ΡŠΡ€ΡΠΈ Π² ΠΊΡƒΠΏΡ‡ΠΈΠ½Π°Ρ‚Π° Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°, Π·Π° Π΄Π° ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅ стойноститС Π½Π° Π΄Ρ€ΡƒΠ³ΠΈΡ‚Π΅ ΠΊΠΎΠ»ΠΎΠ½ΠΈ (Π² Ρ‚ΠΎΠ·ΠΈ случай, ΠΊΠΎΠ»ΠΎΠ½Π°Ρ‚Π° ΠΈΠΌΠ΅ΠΉΠ»), ΠΊΠΎΠΈΡ‚ΠΎ са Π½ΡƒΠΆΠ½ΠΈ Π½Π° заявката.

Π’ PostgreSQL 11 сС появиха ΠΏΠΎΠΊΡ€ΠΈΠ²Π°Ρ‰ΠΈ индСкси. Π’Π΅ позволяват Π²ΠΊΠ»ΡŽΡ‡Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Π΅Π΄Π½Π° ΠΈΠ»ΠΈ няколко Π΄ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π½ΠΈ ΠΊΠΎΠ»ΠΎΠ½ΠΈ Π² самия индСкс β€” Ρ‚Π΅Ρ…Π½ΠΈΡ‚Π΅ стойности сС ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π°Ρ‚ Π² Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅Ρ‚ΠΎ Π½Π° индСкса.

Ако бяхмС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π»ΠΈ Ρ‚Π°Π·ΠΈ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΠ»ΠΈ стойността Π½Π° ΠΈΠΌΠ΅ΠΉΠ»Π° Π² индСкса, Ρ‚ΠΎ Π½Π° Postgres Π½Π΅ Π±ΠΈ Π±ΠΈΠ»ΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° Ρ‚ΡŠΡ€ΡΠΈ Π² ΠΊΡƒΠΏΡ‡ΠΈΠ½Π°Ρ‚Π° Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° стойността ΠΈΠΌΠ΅ΠΉΠ». НСка Π²ΠΈΠ΄ΠΈΠΌ Π΄Π°Π»ΠΈ Ρ‚ΠΎΠ²Π° Ρ‰Π΅ Ρ€Π°Π±ΠΎΡ‚ΠΈ:

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β€œ Π½ΠΈ ΠΊΠ°Π·Π²Π°, Ρ‡Π΅ Π½Π° заявката Π²Π΅Ρ‡Π΅ ΠΌΡƒ Π΅ Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π΅Π½ само ΠΈΠ½Π΄Π΅ΠΊΡΡŠΡ‚, ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΏΠΎΠΌΠ°Π³Π° Π΄Π° сС ΠΈΠ·Π±Π΅Π³Π½Π°Ρ‚ всички ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π·Π° дисково Π²Ρ…ΠΎΠ΄/ΠΈΠ·Ρ…ΠΎΠ΄ Π·Π° Ρ‡Π΅Ρ‚Π΅Π½Π΅ Π½Π° ΠΊΡƒΠΏΡ‡ΠΈΠ½Π°Ρ‚Π° Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°.

Π’ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° ΠΏΠΎΠΊΡ€ΠΈΠ²Π°Ρ‰ΠΈΡ‚Π΅ индСкси са Π½Π°Π»ΠΈΡ‡Π½ΠΈ само Π·Π° B-Π΄Π΅Ρ€Π΅Π²ΡŒΡ. ΠžΠ±Π°Ρ‡Π΅ Π² Ρ‚ΠΎΠ·ΠΈ случай усилията Π·Π° ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ ΠΏΠΎ-високи.

ИзползванС Π½Π° частични индСкси

ЧастичнитС индСкси индСксират само подмноТСство ΠΎΡ‚ Ρ€Π΅Π΄ΠΎΠ²Π΅Ρ‚Π΅ Π² Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°. Π’ΠΎΠ²Π° позволява Π΄Π° сС Π½Π°ΠΌΠ°Π»ΠΈ Ρ€Π°Π·ΠΌΠ΅Ρ€ΡŠΡ‚ Π½Π° индСкситС ΠΈ Π΄Π° сС ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ‚ сканиранията ΠΏΠΎ-Π±ΡŠΡ€Π·ΠΎ.

Π”Π° ΠΊΠ°ΠΆΠ΅ΠΌ, Ρ‡Π΅ трябва Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ списък с ΠΈΠΌΠ΅ΠΉΠ» адрСситС Π½Π° Π½Π°ΡˆΠΈΡ‚Π΅ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΈ ΠΎΡ‚ ΠšΠ°Π»ΠΈΡ„ΠΎΡ€Π½ΠΈΡ. Π—Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅Ρ‚ΠΎ Ρ‰Π΅ бъдС Ρ‚Π°ΠΊΠΎΠ²Π°:

SELECT c.email FROM customer c
JOIN address a ON c.address_id = a.address_id
WHERE a.district = 'California';
ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΈΠΌΠ° ΠΏΠ»Π°Π½ Π·Π° Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅, Π²ΠΊΠ»ΡŽΡ‡Π²Π°Ρ‰ сканиранС ΠΈ Π½Π° Π΄Π²Π΅Ρ‚Π΅ ΡΠ²ΡŠΡ€Π·Π°Π½ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†ΠΈ:
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.

ИзползванС Π½Π° ΠΌΠ½ΠΎΠ³ΠΎΠ·Π½Π°Ρ‡Π½ΠΈ индСкси (Multi-Value Indexes)

Някои ΠΊΠΎΠ»ΠΎΠ½ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ трябва Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ индСксирани, ΠΌΠΎΠΆΠ΅ Π΄Π° Π½Π΅ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‚ скаларСн Ρ‚ΠΈΠΏ Π΄Π°Π½Π½ΠΈ. Π’ΠΈΠΏΠΎΠ²Π΅ ΠΊΠΎΠ»ΠΎΠ½ΠΈ ΠΊΠ°Ρ‚ΠΎ jsonb, масиви ΠΈ tsvector ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‚ слоТни ΠΈΠ»ΠΈ мноТСство стойности. Ако трябва Π΄Π° индСксirΠ°Ρ‚Π΅ Ρ‚Π°ΠΊΠΈΠ²Π° ΠΊΠΎΠ»ΠΎΠ½ΠΈ, ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° Ρ‚ΡŠΡ€ΡΠΈΡ‚Π΅ във всички ΠΎΡ‚Π΄Π΅Π»Π½ΠΈ стойности Π² Ρ‚Π΅Π·ΠΈ ΠΊΠΎΠ»ΠΎΠ½ΠΈ.

Π”Π° ΠΎΠΏΠΈΡ‚Π°ΠΌΠ΅ Π΄Π° Π½Π°ΠΌΠ΅Ρ€ΠΈΠΌ ΠΈΠΌΠ΅Π½Π°Ρ‚Π° Π½Π° всички Ρ„ΠΈΠ»ΠΌΠΈ, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‰ΠΈ нарязки ΠΎΡ‚ Π½Π΅ΡƒΡΠΏΠ΅ΡˆΠ½ΠΈ Π΄ΡƒΠ±Π»Π°ΠΆΠΈ. Π’ Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° film ΠΈΠΌΠ° тСкстова ΠΊΠΎΠ»ΠΎΠ½Π°, Π½Π°Ρ€Π΅Ρ‡Π΅Π½Π° special_features. Ако Ρ„ΠΈΠ»ΠΌΡŠΡ‚ Ρ€Π°Π·ΠΏΠΎΠ»Π°Π³Π° с Ρ‚ΠΎΠ²Π° β€žΠΎΡΠΎΠ±Π΅Π½ΠΎ ΡΠ²ΠΎΠΉΡΡ‚Π²ΠΎβ€œ, Ρ‚ΠΎ Π² ΠΊΠΎΠ»ΠΎΠ½Π°Ρ‚Π° ΠΈΠΌΠ° Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° тСкстов масив Π—Π°Π΄ кулиситС. Π—Π° Π΄Π° Π½Π°ΠΌΠ΅Ρ€ΠΈΠΌ всички Ρ‚Π°ΠΊΠΈΠ²Π° Ρ„ΠΈΠ»ΠΌΠΈ, трябва Π΄Π° ΠΈΠ·Π±Π΅Ρ€Π΅ΠΌ всички Ρ€Π΅Π΄ΠΎΠ²Π΅ с β€žΠ—Π°Π΄ ΠΊΡƒΠ»ΠΈΡΠΈΡ‚Π΅β€œ ΠΏΡ€ΠΈ всякакви стойности Π½Π° масива special_features:

SELECT title FROM film WHERE special_features @> '{"Behind The Scenes"}';

ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΡŠΡ‚ Π·Π° ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅ (containment operator) @> провСрява Π΄Π°Π»ΠΈ дясната част Π΅ подмноТСство Π½Π° лявата част.

План Π½Π° Π·Π°ΠΏΠΈΡ‚Π²Π°Π½Π΅Ρ‚ΠΎ:

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-Π΄Π΅Ρ€Π΅Π²ΠΎ Ρ‰Π΅ Π½ΠΈ ΠΏΠΎΠΌΠΎΠ³Π½Π΅:

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-Π΄Π΅Ρ€Π΅Π²ΠΎ Π½Π΅ Π΅ наясно с ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΎΡ‚Π΄Π΅Π»Π½ΠΈ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ Π² индСксируСмитС стойности.

НуТдаСм сС ΠΎΡ‚ 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;
И Π΅Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚Π°, ΠΊΠΎΠ³Π°Ρ‚ΠΎ сС изпълни Π½Π° стоковата Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ pagila:
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 Ρ€Π΅Π΄Π°)

ИндСкси Π½Π° надмноТСства (Superset Indexes)

МоТС Π΄Π° сС случи Ρ‚Π°ΠΊΠ°, Ρ‡Π΅ Π΄Π° Π½Π°Ρ‚Ρ€ΡƒΠΏΠ°Ρ‚Π΅ ΠΌΠ½ΠΎΠ³ΠΎ индСкси, Π΅Π΄ΠΈΠ½ ΠΎΡ‚ ΠΊΠΎΠΈΡ‚ΠΎ индСксира надмноТСство ΠΊΠΎΠ»ΠΎΠ½ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ индСксират Π΄Ρ€ΡƒΠ³ΠΈ индСкси. Π’ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΊΠ°ΠΊΡ‚ΠΎ ΠΆΠ΅Π»Π°Ρ‚Π΅Π»Π½ΠΎ, Ρ‚Π°ΠΊΠ° ΠΈ Π½Π΅ β€” надмноТСство ΠΌΠΎΠΆΠ΅ Π΄Π° Π΄ΠΎΠ²Π΅Π΄Π΅ Π΄ΠΎ сканиранС само ΠΏΠΎ индСкситС, ΠΊΠΎΠ΅Ρ‚ΠΎ Π΅ Π΄ΠΎΠ±Ρ€Π΅, Π½ΠΎ ΡΡŠΡ‰Π΅Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° Π·Π°Π΅ΠΌΠ° Ρ‚Π²ΡŠΡ€Π΄Π΅ ΠΌΠ½ΠΎΠ³ΠΎ място, ΠΈΠ»ΠΈ заявка, Π·Π° оптимизация Π½Π° която Π΅ ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΎ Ρ‚ΠΎΠ²Π° надмноТСство, Π²Π΅Ρ‡Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Π½Π΅ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°.

Ако трябва Π΄Π° Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·ΠΈΡ€Π°Ρ‚Π΅ опрСдСлянСто Π½Π° Ρ‚Π°ΠΊΠΈΠ²Π° индСкси, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅Ρ‚Π΅ ΠΎΡ‚ 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';
с ΠΈΠ·Ρ…ΠΎΠ΄, ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π°Ρ‰ ΠΏΠΎ слСдния Π½Π°Ρ‡ΠΈΠ½:
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 ΠΏΡ€Π΅Π΄Π»Π°Π³Π° мноТСство гъвкави Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈ Π·Π° създаванС Π½Π° индСкси ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π½Π° всякакви спСцифични случаи, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΠΈ Π·Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½Π° Π±Π°Π·Π°Ρ‚Π° Π΄Π°Π½Π½ΠΈ ΠΏΡ€ΠΈ СкспонСнциалСн растСТ Π½Π° Π²Π°ΡˆΠ΅Ρ‚ΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅. НадявамС сС Ρ‚Π΅Π·ΠΈ ΡΡŠΠ²Π΅Ρ‚ΠΈ Π΄Π° Π²ΠΈ ΠΏΠΎΠΌΠΎΠ³Π½Π°Ρ‚ Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ запитванията Π±ΡŠΡ€Π·ΠΈ ΠΈ Π±Π°Π·Π°Ρ‚Π° Π΄Π°Π½Π½ΠΈ Π³ΠΎΡ‚ΠΎΠ²Π° Π·Π° ΠΌΠ°Ρ‰Π°Π±ΠΈΡ€Π°Π½Π΅.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС с Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ πŸ”₯ ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС с Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ | ProHoster