Comments 10
Вот что говорит chatGTP по этому поводу
DEFAULT-значение поля таблицы - это метаданные таблицы, и хранится это значение в структуре. А вот значение поля в конкретной записи - это уже данные. И хранится это значение в теле таблицы. Поэтому никакие манипуляции с DEFAULT (с метаданными) не могут изменить данные уже существующих записей.
А если мы поле, которое не имело ограничения NOT NULL, угостим таким ограничением, то все существующие записи будут проверены на соответствие ограничению. И при обнаружении не соответствующих ограничению записей в изменении структуры нам будет отказано.
Так что "колонка NOT NULL может вернуть NULL" - это галлюцинация ИИ, в принципе невозможная на практике. Можно было даже не экспериментировать..
А вот раскопки с метаданными - это по делу и интересно.
А вот значение поля в конкретной записи - это уже данные. И хранится это значение в теле таблицы
Не всегда. Для новой колонки со значением по умолчанию, "значения поля в конкретной записи" определяется как раз таки метаданными. Весь вопрос был в том, что это за метаданные, т.к. точно не DEFAULT.
Теоретически, мы можем поменятьattmissingval и у миллиона строк поменяется значение за O(1) . На практике - я не смог этого сделать :)
Не всегда.
Абсолютно всегда. Вы просто как-то валите в одну кучу описание данных и сами данные, чего делать категорически нельзя.
Для новой колонки со значением по умолчанию, "значения поля в конкретной записи" определяется как раз таки метаданными.
Именно. Метаданные отвечают на вопрос "какое значение присвоить, если создаётся новая запись, а значение для поля не указано". тогда как данные отвечают на вопрос "какое значение хранится в данном поле у данной конкретной уже существующей записи".
Теоретически, мы можем поменять
attmissingvalи у миллиона строк поменяется значение за O(1)
Нет, нет и ещё раз нет! Значение НЕ поменяется. Потому что и запись, и соответственно значение поля, УЖЕ существуют и УЖЕ хранятся в теле данных таблицы. И им ну совершенно сиренево, что там происходит в метаданных.
Весь вопрос был в том, что это за метаданные, т.к. точно не DEFAULT.
Почему я и сказал, что раскопки в метаданных - это интересно.
Нет, нет и ещё раз нет! Значение НЕ поменяется. Потому что и запись, и соответственно значение поля, УЖЕ существуют и УЖЕ хранятся в теле данных таблицы.
Либо я чего-то не понимаю, либо это не так.
Смотри, я создал колонку со значением по умолчанию. И размер таблицы не изменился. Как значение может храниться в теле таблицы, если размер таблицы не изменился?before_add_column | 3568 kB after_add_column_default | 3576 kB
Далее идём в доку:
attmissingval anyarray
Значение в этом элементе используется, когда столбец полностью отсутствует в строке, что имеет место, когда столбец добавляется с неизменчивым значением
DEFAULTпосле создания строки.
До 11 версии при создании колонки с дефолтом строки в таблице физически обновлялись и всё было так как ты говоришь. А сейчас это поведение имитируется с помощью attmissingval.
Блин. Поля НЕ БЫЛО! Ты его только что создал. Если не было поля - не было и значения в этом поле. Вот объясни мне, дураку, как нечто не существующее может ПОМЕНЯТЬСЯ? Поменяться может только существующее значение - некое конкретное или признак отсутствия ака NULL. Было старое значение, стало новое - это называется поменяться. А у тебя значение ПРИСВОЕНО. Что называется, "с нуля". Раньше не было, теперь есть.
И это косвенно подтверждается тем, что значение, записанное в attmissingval, не изменяется при изменении DEFAULT. Потому что либо запись существовала на момент создания поля, и тогда ему было присвоено начальное DEFAULT, но оно не записано в тело записи, и его надо брать из attmissingval, либо запись не существовала и была создана позднее - тогда в тело данных записи сразу было записано значение этого поля, взятое из column_default. И для записи, которая существовала, при любом её изменении будет записано новое состояние этой записи, на сей раз уже с внесённым туда полем и его значением, взятым из attmissingval. И уже по телу записи невозможно определить, была ли запись на момент создания поля, или была вставлена позже.
Postgresql имитирует наличие значения, подставляя его при чтении из метаданных.
Когда писал про изменение значения в миллионах строк, я рассуждал с точки зрения потребителя. Читаю таблицу, получаю одно значение. Меняю метаданные, читаю таблицу ещё раз, получают другое значение. В самой таблице, физически, конечно, ничего не меняется.
Могу переформулировать: теоретически, мы можем поменятьattmissingval и это будет выглядеть, как-будто, у миллиона строк поменяется значение за O(1) . На практике - я не смог обновить attmissingval.
Давай лучше выясним, с чем мы согласны :)
Согласен ли ты, что при создании новой not null колонки со значением по умолчанию, значения в строках таблицы не изменяются. А при чтении строк созданных до добавления колонки, значение для колонки возвращается из attmissingval?
Согласен ли ты, что при создании новой not null колонки со значением по умолчанию, значения в строках таблицы не изменяются.
Да, согласен. Изменение метаданных не затрагивает область данных. Я вроде об этом говорил.
А при чтении строк созданных до добавления колонки, значение для колонки возвращается из
attmissingval?
И с этим согласен. И об этом я тоже говорил.
я рассуждал с точки зрения потребителя
Ну тогда надо чётко делить - вон там я говорил о внешнем эффекте, а вот тут о технической стороне вопроса. Иначе и возникают подобные непонимания.
Читаю таблицу, получаю одно значение. Меняю метаданные, читаю таблицу ещё раз, получают другое значение.
Вот опять. Читаешь таблицу, и НЕ получаешь поля, о котором говоришь, ибо оно не создано, и его в структуре нет. Меняешь метаданные, создавая поле, читаешь таблицу, и теперь получаешь запись другой структуры, со свежесозданным полем. Это не ДРУГОЕ значение. Потому что твоего "одного значения" - не было, а получение этого "одного значения" - галлюцинация из-за неаккуратной формулировки.
На практике - я не смог обновить
attmissingval.
Конечно, это же запрещено. Нет, можно остановить Постгресс, влезть грязными лапами через какой-нить бин-редактор в файл метаданных, поправить значение, снова запустить Постгресс и посмотреть, скушает ли он это изменение и покажет ли теперь изменённое значение. Я, правда, сомневаюсь, и сильно надеюсь, что Постгресс по каким-нибудь внутренним контрольным суммам сумеет обнаружить стороннее изменение и завопит о разрушении данных, но надо проверять.
Рад, что в целом мы согласны.
Я говорил про сценарий: создали колонку, прочитали, поменяли attmissingval, прочитали другое значение. Ты же говоришь про: прочитали, создали, прочитали. Я же правильно понял?
Хз, почему ты так решил, я изначально говорил "мы можем поменятьattmissingval ", а значит колонка уже должна существовать.
Конечно, это же запрещено.
И правильно, а всё-равно было бы интересно попробовать :)
constraint проверяется только при INSERT/UPDATE а не при изменении metadata
Уж очень явная галлюцинация. Единожды испытав боль от добавления нового constraint в существующую таблицу, ошибиться в этом уже нереально, как мне кажется.
Но что-то мы отстаем от повестки сообщества, там ИИ-агенты уже сами себя и всё вокруг пишут без участия программиста, а мы про какие-то галлюцинации :)
Где в postgresql хранится default-значение созданной колонки?