Как я понимаю документацию, следующие определения эквивалентны:
create table foo (
id serial primary key,
code integer,
label text,
constraint foo_uq unique (code, label));
create table foo (
id serial primary key,
code integer,
label text);
create unique index foo_idx on foo using btree (code, label);
Тем не менее, примечание в руководстве к Postgres 9.4 гласит:
Предпочтительным способом добавления уникального ограничения в таблицу является
ALTER TABLE ... ADD CONSTRAINT
. Использование индексов для обеспечения уникальных ограничений может рассматриваться как деталь реализации, к которой нельзя обращаться напрямую.
(Изменить: эта заметка была удалена из руководства с Postgres 9.5.)
Это только вопрос хорошего стиля? Каковы практические последствия выбора одного из этих вариантов (например, в исполнении)?
sql
postgresql
unique
Адам Пиотровски
источник
источник
Ответы:
У меня были некоторые сомнения по поводу этой основной, но важной проблемы, поэтому я решил учиться на собственном примере.
Давайте создадим мастер тестовой таблицы с двумя столбцами, con_id с уникальным ограничением и ind_id, индексированные по уникальному индексу.
В описании таблицы (\ d в psql) вы можете отличить уникальное ограничение от уникального индекса.
уникальность
Давайте проверим уникальность, на всякий случай.
Работает как положено!
Внешние ключи
Теперь мы определим детальную таблицу с двумя внешними ключами, ссылающимися на наши два столбца в master .
Ну, без ошибок. Давайте удостоверимся, что это работает.
На оба столбца можно ссылаться во внешних ключах.
Ограничение с использованием индекса
Вы можете добавить ограничение таблицы, используя существующий уникальный индекс.
Теперь нет разницы между описаниями ограничений столбцов.
Частичные индексы
В объявлении ограничения таблицы вы не можете создавать частичные индексы. Он поставляется непосредственно из определения о
create table ...
. В объявлении уникального индекса вы можетеWHERE clause
создать частичный индекс. Вы также можете создать индекс по выражению (не только по столбцу) и определить некоторые другие параметры (параметры сортировки, порядок сортировки, размещение NULL).Вы не можете добавить ограничение таблицы, используя частичный индекс.
источник
Еще одно преимущество использования
UNIQUE INDEX
vs.UNIQUE CONSTRAINT
заключается в том, что вы можете легкоDROP
/CREATE
индексироватьCONCURRENTLY
, тогда как с ограничением вы не можете.источник
Полный текст
Так что скоростные показатели должны быть одинаковыми
источник
Еще я столкнулся с тем, что вы можете использовать выражения sql в уникальных индексах, но не в ограничениях.
Итак, это не работает:
но следующие работы.
источник
citext
расширение.Поскольку разные люди предоставили преимущества уникальных индексов над уникальными ограничениями, вот недостаток: уникальное ограничение может быть отложено (проверяется только в конце транзакции), уникальный индекс не может быть.
источник
Я прочитал это в документе:
Поэтому я думаю, что это то, что вы называете «частичной уникальностью», добавляя ограничение.
И о том, как обеспечить уникальность:
Поэтому мы должны добавить ограничение, которое создает индекс, чтобы обеспечить уникальность.
Как я вижу эту проблему?
«Ограничение» нацелено на то, чтобы грамматически гарантировать, что этот столбец должен быть уникальным, он устанавливает закон, правило; в то время как «индекс» является семантическим , о «как реализовать, как добиться уникальности, что означает уникальность, когда дело доходит до реализации». Таким образом, способ, которым Postgresql реализует это, очень логичен: сначала вы объявляете, что столбец должен быть уникальным, затем Postgresql добавляет реализацию добавления уникального индекса для вас .
источник
where
, поэтому вы можете определить, что записи являются уникальными, если они удовлетворяют некоторым критериям. Это просто отключает ограничения для неопределенного набора записей, которые предшествуют создаваемому ограничению. Это совершенно другое, и последнее значительно менее полезно, хотя я думаю, что это удобно для прогрессивных миграций.Существует разница в блокировке.
Добавление индекса не блокирует доступ для чтения к таблице.
Добавление ограничения накладывает блокировку таблицы (поэтому все выборки блокируются), поскольку она добавляется через ALTER TABLE .
источник
Очень незначительная вещь, которая может быть сделана только с ограничениями, а не с индексами, - использование
ON CONFLICT ON CONSTRAINT
предложения ( см. Также этот вопрос ).Это не работает:
Это производит:
Преврати индекс в ограничение:
И
INSERT
утверждение сейчас работает.источник