Klasik SQL, bir hücrede birden fazla değer saklamayı öngörmez - ilişkisel model normalizasyon gerektirir. Ancak, günümüz görevlerinde sıkça 'etiket listesi', 'puanlama ölçeği' gibi türler bulunur; burada bir satır seviyesinde birden fazla değerle çalışmak kullanışlıdır. Bazı DBMS’ler (PostgreSQL, Oracle) ARRAY veri türü veya benzeri mekanizmalar sunar.
Dizi kullanımı normalizasyon ilkesini ihlal eder, birçok işlemi (filtreleme, güncelleme, indeksleme) zorlaştırır ve ayrıca kodun DBMS'ler arasında taşınabilirliğini azaltır. Ancak, bazı durumlarda uygun veya zorunlu olabilir - örneğin, önbellekleme veya küçük değer listeleri üzerinde hızlı arama için.
CREATE TABLE products ( id SERIAL PRIMARY KEY, tags TEXT[] ); -- Eklemek: INSERT INTO products(tags) VALUES (ARRAY['eco','sale','hot']); -- Dizi üzerinde arama: SELECT * FROM products WHERE 'eco' = ANY (tags);
Anahtar özellikler:
Dizinin bireysel elemanlarını indekslemek mümkün mü?
PostgreSQL’de - evet, GIN/GIST indeksleri aracılığıyla:
CREATE INDEX idx_tags ON products USING GIN (tags);
String sütunundaki ayırıcıyla değerin dizide bulunup bulunmadığını nasıl daha hızlı kontrol edelim?
SQL standart olarak bunu yapamaz, genellikle şablonla arama kullanılır:
SELECT * FROM users WHERE ',admin,' like concat('%,',role,',%');
Ama bu yaklaşım güvenilir değil ve yavaştır.
Dizide ne kadar değer saklanabilir ve ne kısıtlar?
Kısıtlama DBMS’e bağlıdır - örneğin PostgreSQL’de, sadece satır boyutuna (1-2 MB) bir kısıtlama vardır.
E-ticaret projesinde ürün etiketlerini bir sütunda virgülle string olarak saklamaya karar verildi. Etiket bazında ürünlerin hızlı araması çok zorlaştı, filtrelemede hatalar oldu ve etiketlerin tekrarı parse hatalarına sebep oldu.
Artılar:
Eksiler:
PostgreSQL’de küçük, değişmez setler (kullanıcı rolleri) için ARRAY ve GIN indeksi kullanıldı. Büyük durumlar için - ayrı bir rol tablosu.
Artılar:
Eksiler: