pg_trgm — fuzzy search, ILIKE tezlashtirish
Mahsulot qidirish: foydalanuvchi "noutbok" deb yozdi (xato). "noutbuk" topilishi kerak. Yoki LIKE '%noutbuk%' so'rovi juda sekin — million qatorda 3 soniya. pg_trgm extension ikkala muammoni hal qiladi.
pg_trgm nima?
Trigram — ketma-ket uchta belgi. "noutbuk" so'zi trigramlarga bo'linadi:
" no" "nou" "out" "utb" "tbu" "buk" "uk "
Ikki matn qanchalik umumiy trigramga ega bo'lsa — shunchalik o'xshash.
CREATE EXTENSION IF NOT EXISTS pg_trgm;
Similarity — o'xshashlik
SELECT similarity('noutbuk', 'noutbok'); -- 0.571428
SELECT similarity('noutbuk', 'telefon'); -- 0.0
-- 0 dan 1 gacha: 1 = bir xil, 0 = hech aloqasi yo'q
ILIKE tezlashtirish — GIN index
Oddiy ILIKE '%matn%' sekin — % boshda bo'lganda index ishlamaydi. pg_trgm bilan GIN index yaratilsa — tez ishlaydi:
CREATE INDEX idx_mahsulot_nomi ON mahsulotlar USING GIN (nomi gin_trgm_ops);
-- Endi tez!
SELECT * FROM mahsulotlar WHERE nomi ILIKE '%noutbuk%';
Fuzzy search — xatoli qidiruv
-- Similarity threshold belgilash
SET pg_trgm.similarity_threshold = 0.3; -- 30% o'xshashlik yetarli
-- Xatoli qidiruv
SELECT nomi, similarity(nomi, 'noutbok') AS ball
FROM mahsulotlar
WHERE nomi % 'noutbok' -- % operatori: similarity > threshold
ORDER BY ball DESC;
-- Natija:
-- nomi | ball
-- noutbuk | 0.57 ← topildi, garchi xato yozilgan bo'lsa ham
LIKE optimizatsiya
-- GIN index bilan barcha LIKE/ILIKE tez ishlaydi
SELECT * FROM mahsulotlar WHERE nomi ILIKE 'nout%'; -- ✅ tez
SELECT * FROM mahsulotlar WHERE nomi ILIKE '%nout%'; -- ✅ tez (pg_trgm bilan)
SELECT * FROM mahsulotlar WHERE nomi ILIKE '%nout'; -- ✅ tez
word_similarity — so'z darajasida
-- Uzun matndagi so'zni qidirish
SELECT word_similarity('noutbuk', 'Eng yaxshi noutbuk va telefon'); -- 1.0
SELECT *
FROM maqolalar
WHERE 'noutbok' <% matn -- word_similarity operatori
ORDER BY word_similarity('noutbok', matn) DESC;
Tez-tez uchraydigan xatolar
Index yaratishni unutish:
-- Extension bor, lekin index yo'q
CREATE EXTENSION pg_trgm;
SELECT * FROM jadval WHERE ustun ILIKE '%matn%'; -- hali ham sekin!
-- Index kerak!
CREATE INDEX ON jadval USING GIN (ustun gin_trgm_ops);
Juda past threshold:
SET pg_trgm.similarity_threshold = 0.1;
-- 10% o'xshashlik — juda ko'p noto'g'ri natija
-- 0.3-0.4 optimal
Xulosa
CREATE EXTENSION pg_trgm;
-- Index (bir marta)
CREATE INDEX ON jadval USING GIN (ustun gin_trgm_ops);
-- So'rovlar
WHERE ustun ILIKE '%qidiruv%' -- tezlashtirilgan
WHERE ustun % 'xatoli_qidiruv' -- fuzzy (similarity)
WHERE 'qidiruv' <% ustun -- word similarity
-- Funksiyalar
similarity(a, b) -- 0..1
word_similarity(so_z, matn) -- 0..1
Keyingi dars
61-dars: TimescaleDB — time-series ma'lumotlar