Existe um limite superior para uma array
coluna?
Estou recebendo esse erro ao inserir no campo array -
PG::Error: ERROR: index row size 3480 exceeds maximum 2712 for index "ix_data"
Aqui está a minha definição de tabela -
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);
Preciso de um índice no campo array, pois estou fazendo algumas pesquisas nele.
data
contém uma lista de tags como demonstradas nesta postagem de blog relacionada por Scott Snyder ? Se for esse o caso, talvez eu tenha uma solução melhor para você.Respostas:
O problema
Aqui está um caso muito semelhante discutido no pgsql.general . É sobre a limitação em um índice de árvore b, mas é o mesmo porque um índice GIN usa um índice de árvore b internamente para chaves e, portanto, é executado na mesma limitação para o tamanho da chave (em vez do tamanho do item em uma árvore b simples índice).
Cito o manual sobre a implementação do índice GIN :
De qualquer forma, pelo menos um elemento da matriz em sua coluna
data
é muito grande para ser indexado. Se esse for apenas um valor estranho ou algum tipo de acidente, você poderá truncar o valor e concluir o processo.Para os fins da seguinte demonstração, assumirei o contrário: muitos valores de texto longo na matriz.
Solução simples
Você pode substituir elementos em sua matriz
data
por valores de hash correspondentes . E envie valores de pesquisa através da mesma função hash. Obviamente, você provavelmente deseja armazenar seus originais em algum lugar. Com isso, quase chegamos à minha segunda variante ...Solução avançada
Você pode criar uma tabela de consulta para elementos de matriz com uma
serial
coluna como chave primária substituta (efetivamente um tipo radical de valor de hash) - o que é ainda mais interessante se os valores dos elementos envolvidos não forem exclusivos:Como queremos procurar
elem
, adicionamos um índice - mas um índice a uma expressão dessa vez, com apenas os 10 primeiros caracteres do texto longo. Isso deve ser suficiente na maioria dos casos para restringir uma pesquisa a um ou alguns hits. Adapte o tamanho à sua distribuição de dados. Ou use uma função hash mais sofisticada.Sua coluna
data
seria do tipoint[]
. Renomeei a mesadata
e me livrei do sinistro quevarchar(50)
você tinha no seu exemplo:Cada elemento da matriz
data
refere-se a aelem.elem_id
. Nesse ponto, você pode considerar substituir a coluna da matriz por uma tabela n: m, normalizando assim seu esquema e permitindo que o Postgres imponha integridade referencial. A indexação e o manuseio geral se tornam mais fáceis ...No entanto, por razões de desempenho, a
int[]
coluna em combinação com um índice GIN pode ser superior. O tamanho do armazenamento é muito menor. Nesse caso, precisamos do índice GIN:Agora, cada chave do índice GIN (= elemento da matriz) é um em
integer
vez de um longotext
. O índice será menor em várias ordens de magnitude; as pesquisas, consequentemente, serão muito mais rápidas.A desvantagem: antes que você possa realmente fazer uma pesquisa, é necessário procurar
elem_id
na tabelaelem
. Usar o meu índice funcional recém-introduzidoelem_elem_left10_idx
também será muito mais rápido.Você pode fazer tudo isso em uma consulta simples :
Você pode estar interessado na extensão
intarray
, que fornece operadores e classes de operadores adicionais.Demonstração ao vivo totalmente funcional no sqlfiddle.
fonte
O erro está no índice
ix_data
, não notext[]
campo. O tamanho máximo de uma linha nesse tipo de índice específico é limitado a2712
bytes. Se você soltar seu índice e tentar inserir novamente, ele deverá funcionar para você. Se você precisar indexar um campo maior, convém examinar os recursos de indexação de texto completo do postgres.fonte
Eu estava recebendo isso em uma coluna de geografia do PostGIS. Foi porque eu acidentalmente criei o índice incorretamente. Você deve incluir o parâmetro USING GIST ao criar esses índices.
fonte