CHAR или VARCHAR ? А может быть BLOB ?

создан в 1997 году. откорректирован 24.06.2002, 24.01.2003.

Особенности строковых типов данных

Давайте сначала повторим описание этих типов данных из документации (Data Definition Guide):
  • CHAR(n) - n символов, от 1 до 32767, строковый тип фиксированной длины. Если содержимое поля меньше указанного размера, то оно "выравнивается" (добивается) дополнительными пробелами.
  • VARCHAR(n) - n символов, от 1 до 32767, строковый тип переменной длины. Пробелы в конце содержимого поля игнорируются.
  •  

    Максимальная длина строковых типов зависит от используемого набора символов. Наборы символов перечислены в Data Defintion Guide (Appendix A) и в Language Reference (Appendix D). Для каждого набора указано, сколько байт занимает один символ. Если один символ набора занимает больше одного байта, то максимальна длина строкового поля будет 32767/кол-во_байт_на_символ (т.е. для UNICODE_FSS - 10922 символа).

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

    Количество концевых пробелов учитывается только для varchar. Значение char "добивается" пробелами до объявленной длины только тогда, когда с ним производятся операции присвоения или передача данных на сторону клиента.

    Поэтому, с точки зрения эффективности хранения различия между char и varchar практически нет. И для работы нужно выбирать то, что удобнее. Как правило это varchar.

    Клиентские компоненты могут (или не могут) осуществлять обрезание концевых пробелов для столбцов CHAR. В зависимости от склонностей разработчика такого набора обрезание пробелов может быть по умолчанию, а может и потребовать установки в True какого-либо свойства или на уровне DataSet, или на уровне конкретного поля (TStringField). Поэтому, если вас замучили концевые пробелы в строках, посмотрите на свойства компонент.
    Нужно отметить, что ни BDE ни dbExpress не могут выполнять обрезание концевых пробелов у строк.

    Поля типа BLOB

    Поля этого типа позволяют хранить безразмерную произвольную двоичную информацию (поэтому поля типа BLOB не имеют свойства "набор символов"). Запись на диск производится сегментами. Дисковый сегмент блоба это вовсе не то, что имеется в виду при объявлении столбца BLOB (SEGMENT SIZE xx). Сервер сам разбирается, как хранить конкретное значение blob на диске. Указание размера сегмента при объявлении столбца BLOB не даст никакого выигрыша или проигрыша в производительности. Оно нужно только для приложений, написанных на C (Embedded SQL) при помощи GPRE. Например в IBX размер буфера для чтения-записи blob определен жестко в 16К, и именно такими "сегментами" оперирует IBX. Поэтому определять размер сегмента при объявлении blob не имеет смысла.

    Существуют предопределенные подтипы (SUB_TYPE) BLOB: 0 - двоичные данные, 1 - текстовые данные. На самом деле разницы между ними нет, и подтип имеет значение только для вашего приложения (или при написании фильтров BLOB). Пользовательские подтипы можно определить, указав SUB_TYPE с отрицательным знаком - -1, -2, -10, -200 и т.д., и опять-же это имеет значение только для приложения, работающего с данными или для фильтра.

    Сегменты BLOB всегда записываются на свободное пространство, и занимают только действительный объем данных BLOB.
    Если размер BLOB превышает размер страницы, то создается массив указателей на страницы BLOB. При очень больших размерах BLOB могут появиться указатели на страницы указателей BLOB.
    При изменении записи, если содержимое blob не менялось, его blobID остается тем же самым. Собственно, в новой версии записи пишутся только те поля, которые были изменены. Следовательно, при модификации записи, если не затронуто поле BLOB, данные blob не "дублируются". Если же блоб меняется, то как и версия записи, он находится на диске в двух экземплярах - старом и новом. Учитывайте это для блобов, хранящих большой объем данных.

    примечание: Индексировать по полям BLOB невозможно.

    CHAR или BLOB ?

    Итак, мы рассмотрели все аспекты хранения данных CHAR, VARCHAR и BLOB, и теперь можем перечислить рекомендации по выбору типа.
  • если длина поля < 255 символов, то
  • если длина поля > 255, но < ~10000 символов
  • если длина поля > ~5000 символов, или информация может быть произвольной
  • дополнительным фактором выбора может быть размер страницы. При размере страницы 8К можно для хранения строк выбирать CHAR или VARCHAR, если их длина также не превысит 8К (записи могут пересекать страницы, поэтому даже при размере страницы 1К можно объявлять строки длиной 32К). Неплохо в таких случаях создать тестовую таблицу, и попробовать скорость или удобство считывания разных вариантов типов полей, наполнив char, varchar и blob одними и теми же данными.
  • Конвертация данных

    В Firebird и Yaffil, в 3-м диалекте появилась возможность при insert (update?) содержимое блоба задавать обычной строкой. В остальных серверах при подобных действиях будет выдано стандартное сообщение о невозможности конвертации данных.

    Вместе с тем уже давно существуют UDF перевода блоба в строку и обратно (FreeUDFLib и другие).

    Возможные проблемы


    (с) 1997 KDV, www.ibase.ru