CodeGym /Kurslar /SQL SELF /JSONB tipli dataların indekslənməsi: ...

JSONB tipli dataların indekslənməsi: GINBTREE indekslərindən istifadə

SQL SELF
Səviyyə , Dərs
Mövcuddur

İlk sual: ümumiyyətlə niyə JSONB ilə işləyirik? JSONB JSON formatında dataları saxlamağa imkan verir və struktur baxımından çox elastikdir. Bu, xüsusilə datalar mürəkkəb və iç-içə əlaqələrə malik olanda rahatdır (məsələn, istifadəçi profilləri, ünvan və ya ayarlar siyahısı ilə). Sadə JSON-dan fərqli olaraq, JSONB datanı binar formatda saxlayır, bu da axtarış və filtrasiya əməliyyatlarını xeyli sürətləndirir.

Amma indeks olmadan JSONB üzərində axtarış olduqca ləng ola bilər, xüsusilə cədvəldə minlərlə və ya milyonlarla sətr varsa. Təsəvvür elə, istifadəçi məlumatlarını saxlayan bir cədvəlimiz var və hər istifadəçinin ayarlarını JSONB formatında saxlayırıq. Bu ayarlarda müəyyən bir dəyərə malik istifadəçiləri tapmaq indekssiz — resursları yeyən bir işdir. Burda isə köməyə indekslər gəlir!

JSONB üçün indeksləmə: vacib məqamlar

JSONB ilə işləmək üçün PostgreSQL iki əsas indeksləmə üsulunu dəstəkləyir:

  1. GIN (Generalized Inverted Index)JSONB içindəki açar və dəyərlər üzrə axtarış üçün.
  2. BTREE — sadələşdirilmiş axtarış və sıralama üçün.

Hər birinin öz özəllikləri var. Gəlin, bunlara bir az daha yaxından baxaq.

JSONB üçün GIN indeksi

GIN — güclü bir indeksdir, massivlər, mətnlər və həmçinin JSONB dataları ilə işləyir. O, JSONB obyektinin içindəkiləri açar və dəyərlərə “parçalayır” və sürətli axtarış üçün xüsusi bir struktur yaradır.

JSONB üçün GIN üstünlükləri:

  • Həm açar, həm də dəyərlər üzrə axtarış imkanı verir.
  • Daxili (nested) strukturlarla işləyir.
  • @>, ?, ?|, ?& operatorları ilə əməliyyatları sürətləndirir (açar və dəyərlərin filtrasiya olunması).

Tutaq ki, users adlı bir cədvəlimiz var və settings sütununda istifadəçi ayarlarını JSONB formatında saxlayırıq. Data nümunəsi:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT,
    settings JSONB
);

INSERT INTO users (name, settings) VALUES
('Alice', '{"tema": "qaranliq", "bildirisler": {"email": true, "sms": false}}'),
('Bob', '{"tema": "isiqli", "bildirisler": {"email": false, "sms": true}}'),
('Charlie', '{"tema": "qaranliq", "bildirisler": {"email": true, "sms": true}}');

İndi isə qaranlıq tema (tema: qaranliq) olan bütün istifadəçiləri tez tapmaq istəyirik. Əvvəlcə indeks yaradaq:

CREATE INDEX idx_users_settings_gin ON users USING GIN (settings);

Sonra @> operatoru ilə (dəyər üzrə axtarış):

SELECT name
FROM users
WHERE settings @> '{"tema": "qaranliq"}';

İndi PostgreSQL GIN indeksindən istifadə edir və sorğu xeyli sürətli işləyir.

Bu necə işləyir? JSONB sütununda GIN indeksi yaradanda, PostgreSQL “inverted” indeks qurur, yəni JSON-un bütün açar və dəyərləri üçün ayrıca qeydlər yaradır. Məsələn, bu obyekt üçün:

{"tema": "qaranliq", "bildirisler": {"email": true, "sms": false}}

o, tema, bildirisler.email, bildirisler.sms açarları və onların dəyərləri üçün indeksləmə yaradacaq. Bu, ayrı-ayrı elementlər üzrə axtarışı çox sürətli edir.

JSONB üçün BTREE indeksi

BTREE — klassik indeks növüdür. Əgər sənə JSONB obyektlərini tam şəkildə müqayisə etmək və ya sıralamaq lazımdırsa, istifadə olunur. Amma GIN-dən fərqli olaraq, BTREE JSON obyektinin içini “parçalamır”.

JSONB üçün BTREE üstünlükləri:

  • Obyektlərin sıralanması və müqayisəsi üçün əladır.
  • JSONB “monolit” kimi istifadə olunanda (məsələn, başqa obyektlə müqayisə və ya tam dəyərə görə axtarış) daha sürətli işləyir.

BTREE indeksindən istifadə nümunəsi. Tutaq ki, users cədvəlində settings sütununu tez-tez konkret obyektlə müqayisə edirik:

{"tema": "qaranliq", "bildirisler": {"email": true, "sms": false}}

Əvvəlcə indeks yaradaq:

CREATE INDEX idx_users_settings_btree ON users USING BTREE (settings);

İndi isə obyektlərin müqayisəsi üçün sorğu edə bilərik:

SELECT name
FROM users
WHERE settings = '{"tema": "qaranliq", "bildirisler": {"email": true, "sms": false}}';

Bu sorğu BTREE indeksindən istifadə edəcək və daha sürətli işləyəcək.

GINBTREE müqayisəsi

Xüsusiyyət GIN BTREE
JSONB obyektinin parçalanması Bəli, açar və dəyərlərə bölür Xeyr, tam müqayisə edir
Daxili strukturlar üzrə axtarış Bəli Xeyr
Sıralama Xeyr Bəli
İndeks ölçüsü Daha böyük Daha kiçik
Dəstəklənən operatorlar @>, ?, ?|, ?& =

Yəni, GIN daha mürəkkəb sorğular üçün uyğundur, BTREE isə obyektlərin tam müqayisəsi və ya sıralama lazım olanda işə yarayır.

Hansını seçmək lazımdır?

  • Əgər JSONB içindəki ayrı-ayrı açar və dəyərlər üzrə axtarış etmək istəyirsənsə, GIN istifadə elə.
  • Əgər sənə JSONB obyektlərini tam müqayisə və ya sıralamaq lazımdırsa, BTREE daha yaxşıdır.

Amma unutma ki, bu indeksləri birləşdirmək də olar! Məsələn, eyni sahədə həm GIN, həm də BTREE indeksləri yarada bilərsən, əgər cədvəl hər iki tip sorğuya ehtiyac duyursa.

JSONB indeksləməsində tipik səhvlər

Lazımsız indekslərin yaradılması: Hər JSONB sahəsini indeksləmək həmişə məntiqli deyil. İndekslər yaddaş tutur və insert/update əməliyyatlarını ləngidə bilər.

Nadir istifadə olunan operatorlar üçün indeksləmə: Sadəcə “düzgün” görünür deyə indeks yaratma. Sorğuları analiz elə və indeksləri həqiqətən sürət verən yerlərdə istifadə et.

GIN özəlliklərini nəzərə almamaq: GIN indeksi yaratmaq BTREE-dən daha çox vaxt apara bilər. Böyük cədvəllərdə bunu nəzərə almaq lazımdır.

Praktik tətbiq

JSONB ilə işləmək real layihələrdə faydalıdır, çünki datalar elastik və dinamik olur. Məsələn:

  • İstifadəçi ayarları olan web-applikasiyalar.
  • Fərqli hadisələr üçün müxtəlif sahələri olan logların saxlanması.
  • JSON formatında dataların cache-lənməsi.

Bu dataların GINBTREE ilə indekslənməsi sorğuların performansını xeyli artırır. Məsələn, müsahibədə göstərə bilərsən ki, necə sistemin işini sürətləndirmisən, çətin data strukturları üçün indeksləmə əlavə etməklə.

PostgreSQL-in JSON indeksləri üzrə rəsmi sənədləşməsi buradadır. Nümunələr və dəqiqləşdirmələr üçün ora baxmağı unutma.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION