Изменить varchar в тип boolean в PostgreSQL

я начал работать над проектом, где есть довольно большая таблица (около 82,000,000 строк), которая, я думаю, очень раздута. Одно из полей определяется как:

consistency character varying NOT NULL DEFAULT 'Y'::character varying

он используется как логическое значение, значения всегда должны быть ('Y' | 'N').

Примечание: нет ограничения check и т. д.

Я пытаюсь придумать причины, чтобы оправдать изменение этого поля. Вот что у меня есть:

  • он используется как логическое, так это то. Явное лучше, чем неявное.
  • это защитит от ошибок кодирования, потому что прямо сейчас там все, что может быть преобразовано в текст, будет идти вслепую.

вот мой вопрос(ы).

  • как насчет размера / хранения? БД-UTF-8. Итак, Я думаю там действительно не так много накоплений в этой области. Это должно быть 1 байт для boolean, но также 1 байт для 'Y' в UTF-8 (по крайней мере, это то, что я получить, когда я проверяю длину в Python). Есть ли здесь какие-либо другие накладные расходы на хранение, которые будут сохранены?
  • производительность запроса? И Postgres будет вам прирост производительности, где причиной "=TRUE" и "='Y'"?

2 ответов


PostgreSQL (в отличие от Oracle) имеет полноценный boolean тип. Как правило, флаг "да/нет" должен быть boolean. Это правильный тип для использования!

как насчет размера / хранения?

в основном, a boolean колонки занимает 1 байт на диске
в то время как text или character varying (цитируя руководство ЗДЕСЬ) ...

требование к хранению для короткой строки (до 126 байт) это 1 байт плюс фактическая строка

это 2 байт для простого персонажа. Таким образом, вы можете сократить хранение колонки пополам.

фактическое хранение сложнее, чем это. Есть некоторые фиксированные накладные расходы на таблицу,страница и строка есть NULL для хранения и некоторые типы требуют выравнивание данных. Общее влияние будет очень ограничено - если заметно на все.
подробнее о том, как измерить реальное пространство.

кодирование UTF8 здесь нет никакой разницы. Основные ASCII-символы совместимы с другими кодировками, такими как LATIN-1.

в вашем случае, согласно вашему описанию, вы должны сохранить не нулевое ограничение у вас уже есть-независимо от базового типа.

производительность запроса?

будет немного лучше случае с булевскими. Помимо того, что немного меньше, логика для boolean это проще и varchar или text также, как правило, обременен сортировка конкретные правила. Но не ждите многого от чего-то столь простого.

вместо

WHERE consistency = 'Y'

вы могли бы написать:

WHERE consistency = TRUE

но, действительно, Вы можете упростить просто:

WHERE consistency

дополнительная оценка не требуется.

изменить тип

преобразование таблицы просто:

ALTER TABLE tbl ALTER consistency TYPE boolean
USING CASE consistency WHEN 'Y' THEN TRUE ELSE FALSE END;

этой CASE выражение складывает все, что не TRUE ('Y') to FALSE. Ограничение NOT NULL просто остается.


ни размер хранилища, ни производительность запроса не будут значительно лучше переключаться с одного VARCHAR на логическое значение. Хотя вы правы, что технически чище использовать boolean, когда вы говорите о двоичном значении, стоимость изменения, вероятно, значительно выше, чем выгода. Если вы беспокоитесь о правильности, вы можете поставить проверку на столбец, например

ALTER TABLE tablename ADD CONSTRAINT consistency CHECK (consistency IN ('Y', 'N'));