Есть ли верхняя граница для array
столбца?
Я получаю эту ошибку при вставке в поле массива -
PG::Error: ERROR: index row size 3480 exceeds maximum 2712 for index "ix_data"
Вот мое определение таблицы -
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);
Мне нужен индекс для поля массива, так как я делаю некоторые поиски по нему.
data
содержит список тегов, как показано в этом сообщении в блоге Скотта Снайдера ? Если это так, у меня может быть лучшее решение для вас.Ответы:
Эта проблема
Вот очень похожий случай, обсуждаемый на pgsql.general . Речь идет об ограничении в индексе b-дерева, но это все то же самое, потому что индекс GIN внутренне использует индекс b-дерева для ключей и, следовательно, сталкивается с тем же ограничением для размера ключа (вместо размера элемента в простом b-дереве). показатель).
Я цитирую руководство по реализации индекса GIN :
В любом случае, по крайней мере один элемент массива в вашем столбце
data
слишком велик для индексации. Если это просто единичное значение или какая-то случайность, вы можете усечь значение и покончить с этим.Для следующей демонстрации я буду предполагать иначе: множество длинных текстовых значений в массиве.
Простое решение
Вы можете заменить элементы в вашем массиве
data
соответствующими значениями хеша . И отправлять значения поиска через ту же хеш-функцию. Конечно, вы, вероятно, хотите где-то хранить свои оригиналы. С этим мы почти приходим ко второму варианту ...Усовершенствованное решение
Вы можете создать справочную таблицу для элементов массива со
serial
столбцом в качестве суррогатного первичного ключа (фактически это радикальный вид хеш-значения), что тем более интересно, если значения участвующих элементов не являются уникальными:Так как мы хотим , чтобы посмотреть
elem
, мы добавим индекс - но в индекс на выражении на этот раз, и только первые 10 символов длинного текста. В большинстве случаев этого должно быть достаточно, чтобы сузить поиск до одного или нескольких обращений. Адаптируйте размер к вашему распределению данных. Или используйте более сложную хэш-функцию.Ваш столбец
data
будет иметь типint[]
. Я переименовал стол вdata
и избавился от зловещего, чтоvarchar(50)
вы имели в своем примере:Каждый элемент массива в
data
относится кelem.elem_id
. На этом этапе вы можете рассмотреть возможность замены столбца массива таблицей n: m, тем самым нормализуя вашу схему и позволяя Postgres обеспечивать ссылочную целостность. Индексирование и общая обработка становятся проще ...Однако по соображениям производительности
int[]
столбец в сочетании с индексом GIN может быть лучше. Размер хранилища намного меньше. В этом случае нам нужен индекс GIN:Теперь каждый ключ индекса GIN (= элемент массива)
integer
вместо длинногоtext
. Индекс будет меньше на несколько порядков, следовательно, поиск будет намного быстрее.Недостаток: прежде чем вы действительно сможете выполнить поиск, вы должны посмотреть в
elem_id
таблицеelem
. Используя мой недавно введенный функциональный индексelem_elem_left10_idx
, это тоже будет намного быстрее.Вы можете сделать все это одним простым запросом :
Возможно, вас заинтересует расширение
intarray
, которое предоставляет дополнительные операторы и классы операторов.Полнофункциональная живая демонстрация на sqlfiddle.
источник
Ошибка с индексом
ix_data
, а не сtext[]
полем. Максимальный размер строки в этом конкретном типе индекса ограничен2712
байтами. Если вы отбросите свой индекс и попробуете вставить снова, он должен работать для вас. Если вам нужно проиндексировать большее поле, вы можете изучить возможности полнотекстовой индексации postgres.источник
Я получил это в колонке географии PostGIS. Это потому, что я случайно создал индекс неправильно. Вы должны включить параметр USING GIST при создании таких индексов.
источник