Длина строкового поля в Postgres SQL
У меня есть строка, хранящаяся в базе данных SQL, представляющая URL. Некоторые URL-адреса короткие, а некоторые очень длинные. Я действительно не знаю, какой самый длинный URL-адрес, с которым я могу столкнуться, поэтому, чтобы быть в безопасности, я возьму большое значение, такое как 256 или 512.
Когда я определяю максимальную длину строки (например, используя SQLAlchemy):
url_field = Column(String(256))
Занимает ли это место (память) для каждой строки, даже если фактическая строка короче?
Я предполагаю, что это связано с деталями реализации. Я использую postgreSQL, но меня интересует sqlite, mysql.
3 ответа
Обычно механизмы хранения баз данных могут делать многое, чего вы не ожидаете. Но в основном, есть два типа текстовых полей, которые дают подсказку, что будет происходить внутри.
чар и варчар. Char предоставит вам фиксированный столбец поля, и в зависимости от параметров в сеансе sql, вы можете получить заполненные пробелом строки или нет. Varchar для текстовых полей до определенной максимальной длины.
Поля Varchar могут храниться как указатель вне блока, так что блок сохраняет предсказуемый размер для запросов - но это детали реализации и может варьироваться от дБ до дБ.
В PostgreSQL character(n)
в основном просто varchar
с пробелами на входе / выходе. Это неуклюжий и его следует избегать. Он использует то же хранилище, что и varchar
или же text
поле, которое было дополнено до максимальной длины (см. ниже). char(n)
это историческая бородавка, и ее следует избегать - по крайней мере, в PostgreSQL она не дает никаких преимуществ и имеет некоторые странные причуды с такими вещами, как left(...)
,
varchar(n)
, varchar
а также text
все занимают одно и то же хранилище - длина строки, которую вы указали без заполнения. Используется только хранилище, фактически необходимое для символов, независимо от ограничения длины. Кроме того, если строка имеет значение null, PostgreSQL вообще не сохраняет для нее значения (даже заголовка длины), он просто устанавливает нулевой бит в нулевом растровом изображении записи.
квалифицированный varchar(n)
в основном такой же, как неквалифицированный varchar
с check
ограничение на length(colname) < n
,
Несмотря на то, что говорят некоторые другие комментарии / ответы, char(n)
, varchar
, varchar(n)
а также text
все типы TOASTable. Все они могут храниться вне очереди и / или сжиматься. Для контроля использования хранилища ALTER TABLE ... ALTER COLUMN ... SET STORAGE
,
Если вы не знаете, какая максимальная длина вам нужна, просто используйте text
или неквалифицированный varchar
, Там нет космического штрафа.
Для получения более подробной информации см. Документацию о символьных типах данных, а также некоторые сведения о том, как они хранятся, см. Физическое хранилище базы данных, в частности TOAST.
Демо-версия:
CREATE TABLE somechars(c10 char(10), vc10 varchar(10), vc varchar, t text);
insert into somechars(c10) values (' abcdef ');
insert into somechars(vc10) values (' abcdef ');
insert into somechars(vc) values (' abcdef ');
insert into somechars(t) values (' abcdef ');
Вывод этого запроса для каждого столбца:
SELECT 'c10', pg_column_size(c10), octet_length(c10), length(c10)
from somechars where c10 is not null;
является:
?column? | pg_column_size | octet_length | length
c10 | 11 | 10 | 8
vc10 | 10 | 9 | 9
vc | 10 | 9 | 9
t | 10 | 9 | 9
pg_column_size
размер на диске данных в поле. octet_length
это несжатый размер без заголовков. length
"логическая" длина строки
Итак, как вы можете видеть, char
поле заполнено. Это тратит впустую пространство, и это также дает то, что должно быть очень удивительным результатом для length
учитывая, что входное значение было 9 символов, а не 8. Это потому, что Pg не может определить разницу между начальными пробелами, которые вы вставили в себя, и начальными пробелами, которые он добавил как заполнение.
Так что не используйте char(n)
,
Кстати, если я проектирую базу данных, я никогда не использую varchar(n)
или же char(n)
, Я просто использую text
введите и добавьте соответствующие check
ограничения, если есть требования к приложениям для значений. я думаю что varchar(n)
в стандарте это немного бородавка, хотя я думаю, что это полезно для тех БД, которые имеют макеты на диске, где ограничение размера может повлиять на хранилище.
И postgreSQL, sqllite и mysql применяют стандарт sql для хранения varchar и chars. Что в основном это:
SQL определяет два основных типа символов: переменный символ (n) и символ (n), где n - положительное целое число. Оба этих типа могут хранить строки длиной до n символов. Попытка сохранить более длинную строку в столбце этих типов приведет к ошибке, если только избыточные символы не являются пробелами, в этом случае строка будет усечена до максимальной длины. (Это несколько странное исключение требуется стандартом SQL.) Если строка, которая должна быть сохранена, короче объявленной длины, значения символа символа будут дополнены пробелами; Значения типа символов, меняющихся просто сохранят более короткую строку.
Если кто-либо явно преобразует значение в символ, изменяющий (n) или символ (n), то значение чрезмерной длины будет усечено до n символов без возникновения ошибки. (Это также требуется стандартом SQL.)
Обозначения varchar(n) и char (n) являются псевдонимами для символов, изменяющихся (n) и символа (n), соответственно. символ без спецификатора длины эквивалентен символу (1). Если изменение символов используется без спецификатора длины, тип принимает строки любого размера. Последнее является расширением PostgreSQL.
Ссылка: