2011-02-09 56 views
5

可以在类型为字符串数组的列上创建索引。试用GIN索引。但查询似乎并没有使用这些索引。PostgreSql中字符串列类型的索引数组

Example 

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

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

另外什么是最好的方式来有效地执行'组'列的GROUP BY,以便它可以给'组'和计数。

+3

什么阻止你正常化? – 2011-02-09 15:19:07

+0

实际表格有多个多值列。对于这些列,Db是相对正常化的期望,因为它会降低性能,所以我想避免过多的连接。我使用的'用户'表只是一个例子。 – Anoop 2011-02-09 15:41:34

回答

2

甲杜松子酒索引可用于:

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']); 

结果:

"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" 

在阵列上使用聚集函数,这将是另一个问题。函数unnest()可能会有所帮助。

为什么你不正常化你的数据?这将解决所有问题,包括许多问题,你还没有介入。

+0

我想我没有在查询中使用ARRAY ['Engineering'],结果GIN索引从未被使用过。关于正常化,实际的表格和用例与我所提到的不同。实际表格确实有多列,这些列是用字符串数组表示的多值列。我试图避免多个连接,因为每个表的预期记录数量是几百万的数量级。 – Anoop 2011-02-09 15:35:00

0

我认为处理这个问题的最好方法是标准化你的模型。下面可能会包含错误,因为我没有尝试,但这个想法应该是清楚的:

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'; 

产生的执行计划应该是相当高效了;您可以通过索引ON user_group(group)进行优化,该user_group(group)允许index_scan而不是sequential_scan来查找特定组的成员。