PostgreSQL-də indeksləşdirmə — verilənlər bazasında məlumatları tez tapmağın yoludur. Təsəvvür elə, cədvəldəki məlumatlar kitablar kimidir, indeks isə kitabxanadakı kataloq kimi işləyir: lazım olan kitabı ad və ya müəllifə görə tez tapırsan. JSONB ilə isə iş bir az çətinləşir, çünki məlumatlar strukturlaşdırılmış formada saxlanılır, ayrı-ayrı sətrlər və sütunlar kimi yox.
Əgər JSONB məlumatların həcmi "Harry Potter haqqında kitab, amma şəkilsiz" səviyyəsinə çatırsa, bu struktura daxilində axtarış yavaşlaya bilər. Məsələn, bütün sifarişləri tapmaq istəyirsən, harada ki, müəyyən "status" açarı "delivered" dəyərinə bərabərdir — PostgreSQL bütün qeydləri yoxlamalıdır. Bu, əl ilə etmək istəməyəcəyin bir iş kimi səslənir, düzdür?
Amma GIN və BTREE indeksləri — bizim qəhrəmanlardır, bizi uzun gözləmələrdən xilas edir!
JSONB üçün indeks tipləri
GIN (Generalized Inverted Index)
GIN indeksi xüsusi olaraq strukturlaşdırılmış məlumatlar, məsələn, massivlər və obyektlərlə işləmək üçün yaradılıb, bu da onu JSONB üçün ideal edir. O, obyektin özünü yox, içindəki ayrı-ayrı açar və dəyərləri indeksləyir. Yəni GIN ilə müəyyən açarları, dəyərləri və ya kombinasiyaları tez tapmaq olur.
Təsəvvür elə, JSONB sütununda belə məlumat var:
{"ad": "Alice", "yas": 25, "seher": "Berlin"}
GIN indeksi daxili struktur yaradır, burada "ad", "yas" və "seher" açarları öz dəyərləri ilə əlaqələndirilir. Ona görə də, məsələn, "ad": "Alice" axtaranda PostgreSQL artıq harada axtaracağını bilir — bütün cədvələ baxmır.
BTREE
BTREE indeksi daha klassikdir. O, sıralanmış bir struktur yaradır, hansı ki, konkret dəyərlərə görə məlumatları tez tapmağa imkan verir. JSONB üçün BTREE indeksindən istifadə etmək olar, əgər tam uyğunluq axtarırsan və ya sabit açarın varsa (məsələn, JSONB obyektini tam müqayisə etmək istəyirsən).
Sütunda belə JSONB-obyektlər varsa:
{"ad": "Bob", "yas": 30}
BTREE indeksi faydalı ola bilər, əgər bütün obyektin tam bərabər olduğu qeydləri axtarırsan.
{"ad": "Bob", "yas": 30}
JSONB üçün indeksin yaradılması
Gəlin əvvəlcə GIN indeksini necə yaratmaq lazımdır baxaq. Sadəcə sehrli CREATE INDEX əmri lazımdır. Belə görünür:
-- JSONB sütunu üçün GIN indeksi yaradırıq
CREATE INDEX idx_jsonb_data ON orders USING GIN (data);
Burada:
idx_jsonb_data— indeksin adı.orders— cədvəlin adı.data—JSONBməlumatı olan sütun.
Bu indeksi yaratdıqdan sonra, JSONB içində açar və dəyərləri axtaran sorğular daha sürətli işləyəcək.
Tutaq ki, orders adlı cədvəlimiz var, data sütununda JSONB saxlanılır:
| id | data |
|---|---|
| 1 | {"status": "pending", "total": 100} |
| 2 | {"status": "delivered", "total": 200} |
İndekssiz sorğu:
-- "delivered" statuslu bütün sifarişləri tapırıq
SELECT * FROM orders WHERE data @> '{"status": "delivered"}';
Cədvəl böyükdürsə, bu sorğu çox vaxt apara bilər. Amma GIN indeksi ilə bu sorğu xeyli sürətli işləyəcək.
BTREE indeksini necə yaratmaq olar
BTREE indeksi yaratmaq üçün bir az fərqli yanaşmaq lazımdır. Çox vaxt BTREE ilə JSONB istifadə etmək üçün obyektin özünü yox, bir hissəsini indeksləmək lazımdır. Məsələn:
-- Konkret açar üçün BTREE indeksi yaradırıq
CREATE INDEX idx_jsonb_total ON orders ((data->>'total'));
Burada (data->>'total') açarın dəyərini JSONB obyektindən çıxarır və məhz bu dəyər indekslənir. İndi total = 100 olan sifarişləri axtaranda PostgreSQL bu indeksdən istifadə edəcək.
Eyni məlumatlarla istifadə nümunəsi:
| id | data |
|---|---|
| 1 | {"status": "pending", "total": 100} |
| 2 | {"status": "delivered", "total": 200} |
Sorğu:
-- total = 100 olan bütün sifarişləri tapırıq
SELECT * FROM orders WHERE data->>'total' = '100';
data->>'total' üçün BTREE indeksi ilə bu sorğu xeyli sürətli işləyəcək.
GIN və BTREE müqayisəsi
| Xüsusiyyət | GIN | BTREE |
|---|---|---|
| Nə indekslənir? | JSONB içindəki açarlar və dəyərlər | Göstərilən yol və ya dəyər |
| Ən yaxşı istifadə ssenarisi | Obyektin hissələrinə görə axtarış | Konkret dəyərə görə axtarış |
| İndeksin yaradılma sürəti | Daha yavaş | Daha sürətli |
| Axtarış sürəti | Mürəkkəb strukturlar üçün daha sürətli | Sabit dəyərlər üçün daha sürətli |
| Operator dəstəyi | @>, ?, `? |
,?&` |
Əgər mürəkkəb JSONB strukturların varsa və tez-tez @> və ya ? kimi operatorlardan istifadə edirsənsə, GIN seç. Konkret dəyərlər və ya sabit açarlar axtarırsansa, BTREE daha yaxşıdır.
JSONB indeksləşdirməsində tələlər və tipik səhvlər
JSONB indeksləşdirmə güclüdür, amma bir neçə vacib məqam var ki, diqqətli olmaq lazımdır.
- Lazım olan yerdə indeksin olmaması. Əgər JSONB məlumatları tez-tez
WHEREfiltrində istifadə edirsənsə, amma indeks yaratmamısansa, sorğular yavaş olacaq. - Artıq indeksləşdirmə. Hər mümkün JSONB açarı üçün indeks yaradırsansa, əlavə və yeniləmələr yavaşlayacaq.
- Yanlış indeks tipi seçimi. Sorğuların mürəkkəbdirsə və
@>və ya?kimi operatorlardan istifadə edirsənsə, ammaBTREEindeksi yaratmısansa, performans artımı olmayacaq. - Yollar barədə məlumatsızlıq. Daim iç-içə dəyərlərə müraciət edirsənsə, amma konkret yol üçün indeks yaratmamısansa (məsələn,
data->>'some_key'), sorğun yenə də yavaş olacaq.
Nəticə: hansı indeks nə vaxt istifadə olunmalıdır
- Əgər massivlər və ya mürəkkəb obyektlər varsa, tez-tez açar və dəyərlərə görə axtarış edirsənsə,
GINistifadə et. - Dəqiq uyğunluq və ya konkret açarlara tez-tez baxırsansa,
BTREEistifadə et.
GO TO FULL VERSION