Реклама
Комментарии 6
наличие индекса будет логичным. В этом случае добавление not null constraint будет осуществляться несравнимо быстрее

Не будет.
Как непосредственный автор костыля с «existing constraints on column \»%s\".\"%s\" are sufficient to prove that it does not contain nulls" в pg12 я гарантирую это. set not null и validate constraint индексы использовать не будут.
Индекс для простановки not null имеет смысл только для метода с грязным скальпелем, т.е. изменения системного каталога напрямую.

Самое досадное в коммите — это то, что в сообщении коммита не содержится информации, почему документация изменена.

Это общая политика, хоть системный каталог и доступен на запись — все изменения в нём руками проектом не поддерживаются и любые фейерверки не являются багом. Потому не должны быть в документации.

В итоге, я пришел к такому скрипту

Добавьте LOCK TABLE… IN ACCESS EXCLUSIVE MODE в начало функции. Если бы это не было необходимо для корректной работы — давно бы уже понизили требуемый уровень блокировки…
Спасибо за комментарий и спасибо за костыль с «existing constraints on column \»%s\".\"%s\" are sufficient to prove»! По сути, если индексы не используются, то это единственный способ быстро добавить constraint без прямого использования системных таблиц.

set not null и validate constraint индексы использовать не будут.


Тут я не досмотрел. Сейчас поправлю статью.

все изменения в нём руками проектом не поддерживаются


Да, я так и подумал. Тем не менее, при коммите, меняющем документацию, можно было в двух словах написать об этом.

Добавьте LOCK TABLE… IN ACCESS EXCLUSIVE MODE в начало функции.


Тогда пропадает смысл этом скрипте. Если на столбце есть индекс, то он будет работать быстрее, чем использование 'add constraint'. Если индекса нет, то выигрыша тоже нет.

Я так понял из кода и комментариев, что лок таблицы — это гарантия, что никто не добавит записи с nulls, пока идет проверка перед добавлением constraint. Если я 100% уверен, что этого не произойдет и готов к последствиям, если это произошло, то является ли этот lock обязательным?
По сути, если индексы не используются, то это единственный способ быстро добавить constraint без прямого использования системных таблиц.

Да, потому я и маячил полтора года с патчем «ну давайте хоть так сделаем, больно же not null ставить»

Вообще согласен, коммит неудачный, по правилам проекта в коммите должна быть ссылка на обсуждение (либо пояснение почему её нет), вот эта тема видимо: www.postgresql.org/message-id/flat/20140724122945.GD16857%40alap3.anarazel.de
Я так понял из кода и комментариев, что лок таблицы — это гарантия, что никто не добавит записи с nulls, пока идет проверка перед добавлением constraint.

И что никто не прочитает эту структуру таблицы тоже. И из-за этого не сделает случайно нехорошие вещи. И что не прочитал структуру ранее и не делает нехорошие вещи прямо сейчас. Если готовы взять риск — то ок, но лучше публично не советовать так делать =)

Если на столбце есть индекс, то он будет работать быстрее, чем использование 'add constraint'. Если индекса нет, то выигрыша тоже нет.

Под локом да, необходим индекс будет. Зато можно сделать нулевого размера CREATE INDEX CONCURRENTLY scpecial_index_chk_nulls ON you_big_table (not_null_column) WHERE not_null_column IS NULL; и потом его удалить обратно
Спасибо за подробные разъяснения!

В статье сделан сильный недвусмысленный акцент на то, что работа с системными таблицами — это опасность, нас здесь не ждут, это должно осуществляться лишь в случае, когда уверенность, что nulls отсутствуют и никто туда nulls не добавляет, составляет все 146%.

У себя в проекте я пока использую этот подход, чтобы не делать кунг-фу с созданием временных индексов / check constraints с их последующим удалением. Если инфрастуктура станет менее предсказуемой и уровень хаоса поднимется настолько, что вероятность добавления кем-то null превысит хотя бы 0.1%, то я переключусь на более безопасные альтернативы. Не то, чтобы этих безопасных альтернатив было сейчас очень много) Но они теперь хотя бы есть.

Ещё стоит учитывать, что права на ALTER TABLE mytable и UPDATE pg_attribute могут быть разными.

Только полноправные пользователи могут оставлять комментарии. , пожалуйста.