Pull to refresh

Comments 28

Интересные цифры по размеру индексов. Полезно.
Кстати если типов котов 8 штук как в примере — индекс явно будет неселективный. Тогда уже при фиксированном и неизменном количестве типов логичнее на партицирование перейти.
p.s. да-да, конечно партицирование в постгресе — то еще веселье.
Да, партицирование у нас есть, и там много интересного. Как-нибудь расскажем про это)
А почему было решено не использовать таблицу-справочник с типами котов?
Подразумевается, что список типов котов статичный. В него не будут добавляться новые типы. Так что это ближе к перечисляемому типу, чем к словарю.

Про "не будут добавляться" — это хорошо известная сказка :)

Тут дело в том, рассматриваем ли мы добавление нового типа как штатную операцию, или как некое нештатное действие, требующее митингов, согласований, привлечения девопсов и т. д.

записался на прием, буду ждать.

Всегда было интересно — что заставляет людей, работающих на PostgreSQL, использовать VARCHAR вместо TEXT?
Между ними нет разницы ни по производительности, ни по занимаемой памяти.

Разница только в декларации намерений. Используя TEXT, мы декларируем намерение хранить «длинные тексты». А используя varchar, мы декларируем намерение хранить «короткие строки». Причем разница между «длинным» и «коротким» субъективна.

Это просто дело вкуса.
А почему не используются справочники типов (табличка с типами котов)? Со справочником легко можно добавить новый тип, лучше контроль целостности (FK), меньше избыточность данных (как в архиваторах — создается словарь (справочник), а значение заменяется краткой ссылкой — полем CAT_TYPE::smallint).
Я не эксперт в области принципов работы субд, но разве енамы не превращаются в те самые краткие ссылки?
В общем то да, но это это фиксированно 4 байта (если уж объем так важен) + enum это же фиксированная последовательность. Что вы будете делать если вам понадобился ещё один тип, которого нет в enum'е? Если нужно добавить атрибуты для типа? Если нужно просто переименовать один тип?
Если мне понадобится добавить еще один тип, то я сделаю миграцию ALTER TYPE cat_type ADD VALUE ‘some new value’;

Атрибуты для типа за 3 года эксплуатации не понадобились. А иначе мы бы сделали по-другому.

В целом лучше использовать простые вещи, когда они подходят. А сложные брать когда не подходят простые.
Подразумевается, что список типов котов статичный. Добавлять в него новые типы не нужно.

Контроль целостности обеспечивается самим типом ENUM.

Ну а экономия за счет 2-х байтов smallint вместо 4-х байтов enum, как показал эксперимент, все равно ничего не дает.
Пардон. А в чём тогда был смысл? Просто не приняли во внимание что не будет статичным ENUM или были какие то ещё скрытые моменты?
Если уж на то пошло, то FK (ctype) на ctype_table выглядит как более приемлемое решение, так как вписать в ctype несуществующий id будет проблематично. Плюс к тому же создать новый тип в ctype_table без требуемых прав нельзя, что можно в данном контексте считать контролем целостности.
Смысл перехода от varchar к enum был в том, чтобы ограничить возможные значения type. Заодно, как бонус, получить уменьшение индекса.

Это можно было бы сделать и так, как вы говорите — вынести список возможных типов в отдельную таблицу. Но такой вариант, очевидно, сложнее. Он требует дополнительных действий и на вставке нового кота (сперва нужно получить id типа по имени типа), и на чтении котов (нужно делать join).

ENUM покрывает наши потребности полностью, и делает это более простым способом. Принцип KISS.

Ну и, опять же, декларация намерений. Создавая таблицу с типами мы декларируем, что типы будут меняться — можно добавлять новые и т. д. Создавая ENUM, мы декларируем, что список типов статичен, и меняться не будет.

insert в таблицу — штатная операция. alter type — нештатная операция. То есть мы подчеркиваем, что таких операций не хотим.
Скорее всего Постгрес выравнивает строки по 8 байт, именно поэтому уменьшение длины строки с 60 до 58 байт не дало выигрыша.
Если дополнительно уменьшить имя на 2 символа, то таблица будет упакована плотнее.
Больше интересно, отличается ли производительность при работе с таблицами (int, smallint, smallint) и (smallint, int, smallint)?
Да, за счет типа меньшего размера в одном столбце трудно получить выигрыш. Нужно несколько таких столбцов.

Что касается производительности, то я предположу, что для значений в рамках одного машинного слова она будет одинаковая.
за счет типа меньшего размера в одном столбце трудно получить выигрыш

Если строк много и длина их переменна (ваш случай), то выигрыш все же будет и он будет соответствовать среднему уменьшению длины записи (если средняя длина записи уменьшится с 50байт до 48байт то и таблица уменьшится на ~4%)
Если вы всё ещё продолжаете гладить котов, я бы не стал делать ALTER на ENUM.
Как мне кажется, эксклюзивная блокировка всех таблиц, которые этот ENUM используют — не лучшее решение для того чтобы поглаживать котов.
В документации на ALTER TYPE ничего не написано про блокировки. И здравый смысл подсказывает, что нет никакой необходимости блокировать какие-либо таблицы при добавлении нового значения в ENUM. Вот при удалении значения, да, блокировки могут понадобится.
В всей этой миграции несколько смущает моемнт, что у каких-то котов с более неиспользуемыми типами этот типа взяли и заменили на NULL. То есть данные вообще пропали. Может надо было их куда-то в соседнюю таблицу выгрузить? Хотя это, конечно, вопрос к бизнесу, а не к базе как таковой.
Да, можно было бы сохранить куда-то. Но нашем случае это не нужно.
Функция pg_indexes_size показывает расход памяти суммарно по всем индексам, связанным с таблицей, а не по каждому отдельно.


SELECT relname, relpages FROM pg_class WHERE relname LIKE '...';
покажет размер (в 8КБ страницах) каждого индекса (и таблиц)
Sign up to leave a comment.