Qamrovchi indekslar - INCLUDE
Ushbu qo'llanmada PostgreSQLda INCLUDE bandidan foydalanib qamrovchi indekslar (Covering Indexes) yaratish va jadvalning asosiy fayliga (heap) murojaat qilmasdan, to'g'ridan-to'g'ri faqat indeksning o'zidan ma'lumot o'qish (Index Only Scan) usulini o'rganasiz.
Odatda, indeks yordamida qidiruv amalga oshirilganda (Index Scan), PostgreSQL avval indeks daraxtidan kerakli qatorning manzilini topadi, so'ngra so'rovda so'ralgan boshqa ustunlar qiymatini olish uchun jadvalning asosiy ma'lumotlar blokiga (heap file) borib o'qiydi. Bu qo'shimcha disk operatsiyasini (I/O) talab qiladi.
Agar so'rov talab qilayotgan barcha ustunlar indeksning o'zida mavjud bo'lsa, PostgreSQL jadvalning o'ziga murojaat qilishga umuman hojat qolmaydi. U barcha ma'lumotlarni bevosita indeksdan o'qib beradi. Bu Index Only Scan deb ataladi va so'rovni maksimal darajada tezlashtiradi.
Bunday indeks qamrovchi indeks (Covering Index) deb yuritiladi.
PostgreSQL 11 versiyasidan boshlab indeks yaratishda INCLUDE bandi taqdim etilgan:
CREATE INDEX [index_name]
ON table_name (indexed_columns)
INCLUDE (extra_columns);
Farqi shundaki:
indexed_columns — qidiruv, filtrlash va saralash uchun ishlatiladi (B-Tree daraxtining asosiy kalitlari).extra_columns (INCLUDE ichidagi ustunlar) — indeksning faqat eng pastki barg tugunlarida (leaf nodes) qo'shimcha yuk sifatida saqlanadi. Ular daraxt tuzilishini kattalashtirmaydi va B-Tree kalitlari hajmiga cheklov qo'ymaydi, ammo Index Only Scan amalga oshirish uchun yetarli bo'ladi.Avval mahsulotlar jadvalini yaratib, sinov ma'lumotlarini kiritamiz:
DROP TABLE IF EXISTS products CASCADE;
CREATE TABLE products (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price DEC(10, 2) NOT NULL
);
-- 1000 ta qator qo'shamiz
CREATE OR REPLACE FUNCTION insert_products (n INT)
RETURNS VOID
AS
$$
DECLARE
i INT;
BEGIN
FOR i IN 1..n LOOP
INSERT INTO products (name, price)
VALUES (
'Product_' || i,
ROUND((RANDOM() * 100 + 1)::numeric, 2)
);
END LOOP;
END;
$$
LANGUAGE plpgsql;
SELECT insert_products(1000);
Aytaylik, ilovamizda mahsulot nomi bo'yicha qidirib, uning narxini olish juda ko'p takrorlanadi:
SELECT name, price FROM products WHERE name = 'Product_100';
Biz name bo'yicha indeks yaratamiz va INCLUDE yordamida price ustunini unga biriktiramiz:
CREATE INDEX idx_products_name_cover_price
ON products(name)
INCLUDE (price);
EXPLAIN ANALYZE
SELECT name, price
FROM products
WHERE name = 'Product_100';
Natija:
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------
Index Only Scan using idx_products_name_cover_price on products (cost=0.28..4.29 rows=1 width=17) (actual time=0.035..0.036 rows=1 loops=1)
Index Cond: (name = 'Product_100'::text)
Heap Fetches: 0
Planning Time: 0.120 ms
Execution Time: 0.052 ms
E'tibor bering:
Index Only Scan — PostgreSQL jadvalga kirmasdan faqat indeksning o'zidan barcha ma'lumotlarni o'qidi!Heap Fetches: 0 — asosiy jadval bloklariga (heap) nol marta murojaat qilindi.Agar biz oddiy CREATE INDEX ON products(name) yaratganimizda, narxni olish uchun albatta heap faylga borib o'qishi kerak bo'lardi (Heap Fetches > 0).
SELECT ro'yxatida) qaytarilishi kerak bo'lganda.UNIQUE INDEX): siz faqat ma'lum ustunning noyobligini saqlagan holda qo'shimcha ustunlarni qamrab olmoqchi bo'lsangiz:
CREATE UNIQUE INDEX ON users (email) INCLUDE (user_id, full_name);
email noyob bo'ladi, lekin uning qidiruvida user_id va full_name ham bevosita indeksdan olinadi.INCLUDE bandi daraxt kalitiga ta'sir qilmasdan barg tugunlariga qo'shimcha ustunlarni biriktirish uchun qulay vositadir.Heap Fetches: 0 eng tez va tejamkor o'qish operatsiyasini bildiradi.