Будет ли поиск по индексу заметно быстрее с char против varchar, когда все значения равны 36 символам

30

У меня есть устаревшая схема (отказ от ответственности!), Которая использует сгенерированный на основе хеш-кода идентификатор для первичного ключа для всех таблиц (их много). Пример такого идентификатора:

922475bb-ad93-43ee-9487-d2671b886479

Нет надежды на изменение этого подхода, однако производительность с доступом к индексу низкая. Откладывая множество причин , это может быть, есть одна вещь , которую я заметил , что , казалось , меньше оптимальной - несмотря на все значения идентификаторов во всех многих таблиц , являющихся ровно 36 символов в длину, тип столбца varchar(36), не char(36) .

Принесет ли изменение типов столбцов фиксированной длины char(36)какие-либо существенные преимущества в производительности индекса, помимо очень небольшого увеличения числа записей на страницу индекса и т. Д.?

Т.е. работает ли postgres намного быстрее при работе с типами фиксированной длины, чем с типами переменной длины?

Пожалуйста, не упоминайте о незначительной экономии памяти - это не имеет значения по сравнению с операцией, необходимой для внесения изменений в столбцы.

богемский
источник

Ответы:

40

Нет, никакой выгоды вообще . В руководстве прямо говорится :

Совет: между этими тремя типами нет разницы в производительности , за исключением увеличения места для хранения при использовании типа с пробелом и нескольких дополнительных циклов ЦП для проверки длины при сохранении в столбце с ограниченной длиной. Хотя character(n)у некоторых других систем баз данных есть преимущества в производительности, в PostgreSQL такого преимущества нет; на самом деле character(n)обычно самый медленный из трех из-за дополнительных затрат на хранение. В большинстве ситуаций text или character varyingдолжны быть использованы вместо .

Жирный акцент мой.

char(n)это в значительной степени устаревший, бесполезный тип. Придерживайтесь varchar(n). Если вам не нужно задавать длину, varcharили textэто будет чуть-чуть быстрее. Вы не сможете измерить разницу.

Кроме того, если все строки имеют длину ровно 36 символов, в любом случае нет сохранения памяти, даже незначительной. Оба имеют одинаковый размер на диске и в оперативной памяти. Вы можете проверить с помощью pg_column_size()(по выражению и по столбцу таблицы).

Связанный:

Вы не просили другие варианты , но я упомяну два:

  1. COLLATION- если вы не используете свою БД с сопоставлением "C" . Сравнение часто пропускается и, возможно, дорого Поскольку ваши строки не кажутся значимыми на естественном языке, вероятно, нет смысла следовать этим COLLATIONправилам. Связанный:

    Обширный сравнительный анализ (среди прочего) влияния COLLATE "C"на производительность:

  2. UUID , очевидно. Ваша строка подозрительно выглядит как UUID (32 шестнадцатеричных числа плюс 4 разделителя). Было бы гораздо эффективнее хранить их как фактическийuuidтип данных, который быстрее несколькими способами и занимает только 16 байтов - в отличие от 37 байтов в ОЗУ для одногоchar(36)илиvarchar(36)(хранится без разделителей, только 32 определяющих символа), или 33 байт на диске. Но выравнивание выравнивания приведет к получению 40 байтов в любом случае.) ТакжеCOLLATIONне имеет значения дляuuidтипа данных.

    SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid

    Это может быть полезно (последние главы):

    Смотрите также:

Эрвин Брандштеттер
источник
Означает ли это, что char / varchar (n) с ограниченной длиной будет тратить циклы ЦП на проверку ограничения, тогда как текстовое поле переменной длины будет хранить текст отдельно менее доступным способом по сравнению с char, который выигрывает в этом сценарии и выигрывает ли это даже стоит подумать, скажем, о 10 миллионах строк с куском текста
PirateApp
1
@PirateApp: char(n)почти никогда не побеждает в любом отношении. Не используйте это. Типы данных textи varchar(без модификатора длины) двоично совместимы и имеют одинаковые характеристики производительности. Существуют исторические причины для того, чтобы оба сосуществовали в Postgres. Внутренне, textэто «предпочтительный» тип среди строковых типов (который может влиять на разрешение типа функции). Циклы ЦПУ для обеспечения выполнения varchar(n)практически не имеют значения. Используйте ограничение длины, когда вам это нужно . В данном случае uuidэто настоящий победитель.
Эрвин Брандштеттер,