¿Hay un límite superior para una array
columna?
Recibo este error al insertar en el campo de matriz:
PG::Error: ERROR: index row size 3480 exceeds maximum 2712 for index "ix_data"
Aquí está mi definición de tabla:
create table test_array(id varchar(50), data text[]);
ALTER TABLE test_array ADD PRIMARY KEY (id);
CREATE INDEX ix_data ON test_array USING GIN (data);
Necesito un índice en el campo de matriz, ya que estoy haciendo algunas búsquedas en él.
data
contiene una lista de etiquetas como las demostradas en esta publicación de blog relacionada de Scott Snyder ? Si ese es el caso, podría tener una mejor solución para usted.Respuestas:
El problema
Aquí hay un caso muy similar discutido en pgsql.general . Se trata de la limitación en un índice b-tree, pero es todo lo mismo porque un índice GIN usa un índice b-tree para las claves internamente y, por lo tanto, se encuentra con la misma limitación para el tamaño de la clave (en lugar del tamaño del elemento en un b-tree simple índice).
Cito el manual sobre la implementación del índice GIN :
De cualquier manera, al menos un elemento de matriz en su columna
data
es demasiado grande para ser indexado. Si esto es solo un valor anormal singular o algún tipo de accidente, es posible que pueda truncar el valor y acabar de una vez.Para el propósito de la siguiente demostración, supondré lo contrario: muchos valores de texto largos en la matriz.
Solución simple
Puede reemplazar elementos en su matriz
data
con los valores hash correspondientes . Y envíe valores de búsqueda a través de la misma función hash. Por supuesto, es probable que desee almacenar sus originales además en algún lugar. Con eso, casi llegamos a mi segunda variante ...Solución avanzada
Podría crear una tabla de búsqueda para elementos de matriz con una
serial
columna como clave primaria sustituta (efectivamente, un tipo radical de valor hash), que es aún más interesante si los valores de los elementos involucrados no son únicos:Como deseamos buscar
elem
, agregamos un índice, pero esta vez un índice en una expresión , con solo los primeros 10 caracteres del texto largo. Eso debería ser suficiente en la mayoría de los casos para limitar una búsqueda a uno o unos pocos resultados. Adapte el tamaño a su distribución de datos. O use una función hash más sofisticada.Su columna
data
sería entonces de tipoint[]
. Cambié el nombre de la tabladata
y me deshice de lo ominosovarchar(50)
que tenía en su ejemplo:Cada elemento de matriz se
data
refiere a aelem.elem_id
. En este punto, puede considerar reemplazar la columna de matriz con una tabla n: m, normalizando así su esquema y permitiendo que Postgres imponga integridad referencial. La indexación y el manejo general se vuelven más fáciles ...Sin embargo, por razones de rendimiento, la
int[]
columna en combinación con un índice GIN puede ser superior. El tamaño de almacenamiento es mucho más pequeño. En este caso, necesitamos el índice GIN:Ahora, cada clave del índice GIN (= elemento de matriz) es un en
integer
lugar de un largotext
. El índice será más pequeño en varios órdenes de magnitud, por lo tanto, las búsquedas serán mucho más rápidas.La desventaja: antes de poder realizar una búsqueda, debe buscar en
elem_id
la tablaelem
. Usando mi índice funcional recién introducidoelem_elem_left10_idx
, esto también será mucho más rápido.Puede hacerlo todo en una consulta simple :
Puede interesarle la extensión
intarray
, que proporciona operadores adicionales y clases de operadores.Demostración en vivo totalmente funcional en sqlfiddle.
fuente
El error está en el índice
ix_data
, no en eltext[]
campo. El tamaño máximo para una fila en ese tipo de índice en particular está limitado a2712
bytes. Si suelta su índice e intenta insertarlo nuevamente, debería funcionar para usted. Si necesita indexar un campo más grande, es posible que desee ver las características de indexación de texto completo de postgres.fuente
Estaba obteniendo esto en una columna de geografía PostGIS. Fue porque accidentalmente creé el índice incorrectamente. Debe incluir el parámetro USING GIST al crear dichos índices.
fuente