2011-02-09 29 views
5

dizesinde dize dizisi dizisi dizin dizisi dizesi dizgisi olan bir sütunda dizin oluşturmak mümkündür. GIN dizinleri kullanılarak denendi. Ancak sorgular bu dizinleri kullanıyor görünmüyor.PostgreSql

Example 

CREATE TABLE users (
name VARCHAR(100), 
groups text[], 
); 

Query: SELECT name FROM users WHERE ANY(groups) = 'Engineering'. 

Ayrıca 'grupları' verip sayabilir verimli şekilde 'grupların sütun üzerinde GROUP BY gerçekleştirmek için en iyi yolu budur.

+3

Sizi normalleştirmekten nasıl koruyorsunuz? –

+0

Gerçek tablonun birden çok değerli sütunları var. Db, performansın yavaşlaması nedeniyle aşırı birleşmelerden kaçınmak istediğim bu sütunlar için nispeten normalleştirildi. Kullandığım 'Kullanıcı' tablosu sadece bir örnektir. – Anoop

cevap

2

bir cin endeksi kullanılabilir:

CREATE TABLE users (
name VARCHAR(100), 
groups text[] 
); 

CREATE INDEX idx_users ON users USING GIN(groups); 

-- disable sequential scan in this test: 
SET enable_seqscan TO off; 

EXPLAIN ANALYZE 
SELECT name FROM users WHERE groups @> (ARRAY['Engineering']); 

Sonucu:

"Bitmap Heap Scan on users (cost=4.26..8.27 rows=1 width=218) (actual time=0.021..0.021 rows=0 loops=1)" 
" Recheck Cond: (groups @> '{Engineering}'::text[])" 
" -> Bitmap Index Scan on idx_users (cost=0.00..4.26 rows=1 width=0) (actual time=0.016..0.016 rows=0 loops=1)" 
"  Index Cond: (groups @> '{Engineering}'::text[])" 
"Total runtime: 0.074 ms" 

başka bir sorun olacağını, bir dizi toplama işlevlerini kullanma. unnest() işlevi işe yarayabilir.

Verilerinizi neden normalleştirmiyorsunuz? Bu, henüz şifreleyici olmayan birçok sorun da dahil olmak üzere tüm sorunları çözecektir.

+0

Sanırım sorguda ARRAY ['Engineering'] kullanmadım ve sonuç olarak GIN endeksi hiç kullanılmadı. Normalleştirmeyle ilgili olarak, gerçek tablo ve kullanım durumu, bahsettiklerimden farklıdır. Gerçek tablonun, dizi dizileri kullanılarak temsil edilen çoklu değerlere sahip çoklu sütunları vardır. Tablo başına beklenen kayıt sayısı milyonlarca olduğu için birden fazla birleşmeden kaçınmaya çalışıyordum. – Anoop

+0

Bence @> operatörü tüm farkları yapar, ANY() dizini kullanamaz gibi görünüyor. –

+0

Özellikle büyük ara ve/veya sonuç tabloları beklediğinizde, verilerinizi mümkün olduğunca DBMS'ye erişilebilir hale getirmelisiniz. Normalleştirme, aksi takdirde değerlerle çalıştığınız birkaç durumda bir referansla çalışmasına izin verir. –

0

Bunun üstesinden gelmenin en iyi yolu, modelinizi normalleştirmek olabilir. Bunu deneyin vermedi olarak şu muhtemelen hataları içerecektir, ama fikir açık olmalıdır:

CREATE TABLE users (id INTEGER PRIMARY KEY, name VARCHAR(100) UNIQUE); 
CREATE TABLE groups (id INTEGER PRIMARY KEY, name VARCHAR(100) UNIQUE); 
CREATE TABLE user_group (
    user INTEGER NOT NULL REFERENCES users, 
    group INTEGER NOT NULL REFERENCES groups); 
CREATE UNIQUE INDEX user_group_unique ON user_group (user, group); 

SELECT users.name 
    FROM user_group 
    INNER JOIN users ON user_group.user = users.id 
    INNER JOIN groups ON user_group.group = groups.id 
    WHERE groups.name = 'Engineering'; 

çıkan yürütme planı zaten oldukça verimli olmalıdır; Belirli bir grubun üyelerini bulmak için bir sequential_scan yerine bir index_scan sağlayan ON user_group (group) indeksleme yaparak optimizasyon yapabilirsiniz.

+0

Bu özel kullanım durumu için normalizasyondan kaçınmak istedim. Dizilim dizisi veri türünü kullanmak zorunda kalmamın nedeni budur. – Anoop