2011-02-09 5 views
5

Es posible crear un índice en una columna cuyo tipo es matriz de cadenas. Intentó usar índices GIN. Pero las consultas no parecen estar usando esos índices.matriz de indización de tipo de columna de cadenas en PostgreSql

Example 

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

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

también cuál es la mejor manera de realizar GROUP BY en la columna 'grupos' de manera eficiente para que pueda dar 'grupos' y contar.

+3

¿Qué le impide la normalización? –

+0

La tabla real tiene múltiples columnas de valores múltiples. Db es relativamente normalizado, espere para estas columnas donde quería evitar uniones excesivas, ya que está ralentizando el rendimiento. La tabla 'Usuario' que utilicé es solo un ejemplo. – Anoop

Respuesta

2

Un índice gin se puede utilizar:

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

Resultado:

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

Uso de las funciones agregadas en una matriz, que será otro problema. La función unnest() podría ayudar.

¿Por qué no normalizas tus datos? Eso solucionará todos los problemas, incluidos muchos problemas que aún no has encontrado.

+0

Creo que no utilicé ARRAY ['Ingeniería'] en la consulta y, como resultado, nunca se utilizó el índice GIN. En cuanto a la normalización, la tabla real y el caso de uso son diferentes de los que he mencionado. La tabla real tiene múltiples columnas que están multivaluadas mediante una matriz de cadenas. Estaba intentando evitar las combinaciones múltiples ya que el número esperado de registros por tabla es del orden de millones. – Anoop

+0

Creo que el operador @> marca la diferencia, parece que CUALQUIERA() no puede usar el índice. –

+0

Específicamente, cuando espere tablas intermedias y/o de resultados grandes, debe hacer que sus datos sean tan accesibles para el DBMS como sea posible. La normalización le permite trabajar con una referencia en varios casos en los que de lo contrario trabajaría con valores. –

0

Creo que la mejor manera de manejar esto sería la normalización de su modelo. El siguiente es probable que contenga errores, ya que no lo probamos, pero la idea debe ser claro:

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

El plan de ejecución resultante debe ser bastante eficiente ya; puede optimizar todavía indexando ON user_group (group), que permite que index_scan en lugar de sequential_scan encuentre los miembros de un grupo en particular.

+0

Quería evitar la normalización para este caso de uso en particular. Esa es la razón por la que me vi obligado a usar una matriz de tipos de datos de cadenas. – Anoop

Cuestiones relacionadas