Какое максимальное количество символов может хранить переменная типа char
Перейти к содержимому

Какое максимальное количество символов может хранить переменная типа char

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

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

Количество концевых пробелов учитывается только для 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?

  • Если длина поля < 255 символов, то
    • лучше использовать VARCHAR – по хранению varchar на 2 байта больше char, зато в приложениях не надо писать отрезание концевых пробелов у строк.
    • в старых версиях IB при использовании VARCHAR могут возникнуть проблемы с производительностью при использовании протокола TCP/IP.
    • не имеет смысла использовать BLOB – выборка BLOB осуществляется по его идентификатору, поэтому происходит чуть дольше и требует немного больше затрат на программирование.
    • Можно использовать как CHAR или VARCHAR, так и BLOB. Индексирование по полями такой длины невозможно, к тому же есть шанс что однажды записываемые данные превысят 10000 символов, и может быть BLOB подойдет больше. Ориентируйтесь только на удобство работы с такими данными в приложении.
    • лучше использовать BLOB. Подтип может быть любой, информацию в таком поле можно хранить произвольную и не беспокоиться о размере данных. Стоимость доступа к данным такого размера полностью компенсирует разницу в способах хранения и извлечения полей типа CHAR и BLOB.

    Конвертация данных

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

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

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

    Индексирование

    • Строковые независимо от типа поля имеют ограничение на длину индекса – 84 байта при указании COLLATE и 252 байта – без COLLATE.
    • BLOB-поля не могут быть проиндексированы.

    Поиск

    • Для поиска по полям типа CHAR, VARCHAR и BLOB можно использовать операторы STARTING WITH (начинается с), LIKE (начинается, содержит, или заканчивается на) и CONTAINING (содержит). В BLOB этими операторами можно искать произвольную информацию (необязательно текстовую), однако необходимо учитывать что поиск в BLOB может осуществляться только перебором записей.
    • Если поиск производится по окончанию, например, LIKE ‘%ов’, то такой запрос по полю CHAR выдаст 0 записей, если длина значения поля хотя бы на один символ меньше объявленной длины поля. Это происходит потому, что CHAR при сравнении добивается до длины поля пробелами, и получается, что ‘Иванов ‘ не подходит под условие поиска ‘%ов’. Для решения этой проблемы нужно пользоваться VARCHAR
    • Поиск или упорядочивание (ORDER BY) с использованием функции UPPER возможен только для полей типа CHAR или VARCHAR, т. к. только они имеют свойство CHARACTER SET (BLOB содержит только произвольную двоичную информацию, т. е. необязательно текстовую). Кроме того, для UPPER поля CHAR и VARCHAR должны иметь соответствующий COLLATE либо в объявлении типа поля, либо в выражении поиска или сортировки.

    Примечание. Вы можете написать собственную функцию, аналогичную UPPER, и избежать указанной проблемы.

    Выборка данных

    • При конкатенации строковых полей в запросе нужно учитывать, что CHAR-поля будут «расширены» до указанной длины пробелами, а VARCHAR – нет. Например, если в запросе производится «сборка» фамилии, имени и отчества

    select last_name||first_name||middle_name from clients

    то результат будет приблизительно такой: «Иванов Иван Иванович». А если это будут VARCHAR-поля, то такой же запрос выдаст результат в виде «ИвановИванИванович».

    Для решения этой проблемы можно для CHAR использовать UDF (типа RTrim), а для VARCHAR – вставлять дополнительные пробелы (||» «||).

    • Для многоязыковых баз данных BLOB не могут быть перекодированы из одной кодировки в другую. Например, если сервер поддерживает кодировки WIN1251 и KOI8R, и база создана в WIN1251, возможно подключиться (через компоненты прямого доступа) указывая lc_ctype=KIO8R в параметрах коннекта. При этом информация будет перекодироваться из win1251 в koi8r и наоборот для всех строковых типов данных, кроме BLOB. Для конвертации данных blob хотя бы при выборке придется написать собственную UDF.

    Вставка и модификация данных

    • Поля BLOB невозможно передавать как параметр запроса или хранимой процедуры в BDE 2.5x и 3.x (такая возможность появилась только в BDE 4.0 и у компонент Delphi 3.0). Это приводит к необходимости использования TQuery и передачи данных в BLOB-поля через TBlobStream. Сам сервер не имеет проблем с получением или передачей blob в виде параметров запроса или параметров процедур.

    Создание переносимой базы данных

    • Стандарт ANSI SQL в частности определяет типы полей, но безусловно реализация этих типов, способ хранения и обработки определяет изготовитель конкретного SQL-сервера. Для обеспечения хоть какой-то возможной переносимости следует пользоваться совместимыми типами, игнорируя преимущества использовани типов данных (например CHAR в InterBase). Вам необходимо обратиться к документации или справочным файлам BDE (BDE32.HLP), для того чтобы определить совместимость различных типов между выбранными вами SQL-серверами.

    Copyright iBase.ru © 2002-2023

    Типы данных в MySQL

    В этой инструкции рассказываем про основные типы данных в MySQL и даем советы, где лучше использовать тот или иной тип.

    Эта инструкция — часть курса «MySQL для новичков».

    Смотреть весь курс

    Введение

    При создании таблиц в MySQL для каждого столбца нужно указывать тип данных. Он определяет, какие данные там могут храниться, как будут обрабатываться и сколько места будут занимать. В MySQL все типы данных делятся на несколько классов: числовые типы, символьные, дата/время и так далее. В каждом классе есть несколько типов данных, которые внешне могут быть похожи, но их поведение или принципы хранения отличаются. Важно выбрать правильный тип сразу при создании таблицы, потому что потом готовую структуру и приложения будет сложней переделать.

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

    Возможности MySQL в «Облачных базах данных»

    Числовые типы

    Используются для хранения чисел. Бывают целочисленными, с плавающей точкой и с фиксированной точкой.

    Целые числа

    Хранят только целые числа, без дробной части. Делятся на signed (со знаком) и unsigned (без знака). Типы singed позволяют хранить как положительные, так и отрицательные значения. Типы unsigned хранят только положительные числа, но зато диапазон значений больше. Это может быть полезно в случаях, когда хранимые значения заведомо не могут быть отрицательным. Например, количество товара или идентификатор записи в таблице.

    Тип Размер (байт) Диапазон signed Диапазон unsigned
    TINYINT 1 -128 … 127 0 … 255
    SMALLINT 2 -3 2768 … 32 767 0 … 65 535
    MEDIUMINT 3 -8 388 608 … 8388607 0 … 16 777 215
    INT 4 2 147 483 648 … 2 147 483 647 0 … 42 94 967 295
    BIGINT 8 -2 63 … 2 63 -1 0 … 2 64 -1

    Числа с плавающей точкой

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

    Тип Размер (байт) Диапазон
    FLOAT 4 -3.402823466E+38 … -1.175494351E-38 и 1.175494351E-38 … 3.402823466E+38
    DOUBLE 8 -1.7976931348623157E+308 … -2.2250738585072014E-308 и2.2250738585072014E-308 … 1.7976931348623157E+308

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

    Числа с фиксированной точкой

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

    В MySQL для хранения чисел с фиксированной точкой используются типы DECIMAL(M,D) и NUMERIC(M,D), но по факту это синонимы. Можно использовать любой из этих типов, результат будет одинаковым. В таких столбцах максимально можно хранить до 65 чисел вместе с целочисленной и дробной частями.

    Символьные (строковые)

    Символьные типы используются для хранения текстов. Есть два основных типа: CHAR и VARCHAR. С точки зрения пользователя они выглядят похоже, но MySQL хранит и обрабатывает их по-разному.

    • CHAR хранит строку фиксированной длины до 255 символов. Если длина вставляемой записи меньше, то MySQL автоматически дополняет значение пробелами. Например, если мы указали тип CHAR(10) и сохранили строку «Привет», то по факту в БД будет храниться строка «Привет » (обратите внимание на четыре пробела в конце строки).

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

    • VARCHAR хранит строки переменной длины до 65 535 символов. Причем в памяти хранится именно та длина, которая была указана при создании. VARCHAR занимает меньше места, чем CHAR, но подвержен фрагментации и из-за этого может проигрывать в скорости обработки данных.

    Текстовые и бинарные

    Текстовые (TEXT) и бинарные (BLOB) типы данных используются для хранения больших объемов текста или двоичных данных. Эти типы похожи, но отличаются по способу хранения и обработки внутри MySQL.

    • BLOB обрабатывается как двоичные данные. В нем не хранится набор символов, а операции сортировки и сравнения основаны на числовых значениях байтов.
    • TEXT обрабатывается как символьные строки. В нем хранится именно набор символов, а значения сортируются и сравниваются на основе сопоставления набора символов..

    Текстовые типы отлично подходят для хранения больших текстов: статей, докладов и так далее. А бинарные типы могут хранить любые файлы или мультимедиа-контент.

    Тип Размер (байт) Макс. размер символов
    TINYTEXT / TINYBLOB 255 255
    TEXT / BLOB 65 535 65 535
    MEDIUMTEXT / MEDIUMBLOB 16 777 215 2 24 -1
    LONGTEXT / LONGBLOB 4 294 967 295 2 32 -1

    Кажется, что типы TINYTEXT и TEXT похожи на CHAR и VARCHAR. Но разница в том, что MySQL не умеет индексировать текстовые и бинарные типы и не может использовать индексы для сортировки.

    Дата/время

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

    Тип Размер (байт) Описание
    DATE 3 Только дата в формате YYYY-MM-DD. Допустимые значения от 1000-01-01 до 9999-12-31
    DATETIME 8 Дата и время в формате YYYY-MM-DD HH:MM:SS. Допустимые значения от 1000-01-01 00:00:00 до 9999-12-31 23:59:59
    TIMESTAMP 4 Дата и время. Хранится в виде количества секунд, прошедших с 1 января 1970 года по гринвичу. Занимает в два раза меньше места, чем тип DATETIME. Но при этом диапазон ограничен значениями от 1970-01-01 00:00:01 до 2038-01-09 03:14:07
    TIME 3 Только время в формате HH:MM:SS. Допустимые значения от 00:00:00 до 23:59:59
    YEAR(N) 1 Только год в формате YYYY или YY. Допустимые значения от 1901 до 2155 или от 70 до 69 (1970 — 2069)

    JSON

    Это относительно новый тип данных, который появился в MySQL версии 5.7.8. Он позволяет нативно хранить и обрабатывать данные в JSON-формате.

    В отличие от хранения объектов в виде текста, в использовании специального типа данных есть несколько преимуществ:

    1. Валидация JSON-объектов. Если попытаться сохранить неправильный JSON, MySQL сгенерирует ошибку.
    2. Возможность нативно работать с JSON, выбирать и обновлять только отдельные части объектов, а не весь объект целиком.
    3. MySQL сохраняет тип JSON в специальном внутреннем формате. Такой способ более производительный, чем работа с JSON в виде строки.

    Составные типы

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

    • ENUM может хранить только одно значение из списка, занимает 1-2 байта.
    • SET может хранить одновременно до 64 значений из списка, занимает от 1 до 8 байт.

    Заключение

    Мы рассмотрели основные типы данных и полей в MySQL, объяснили разницу между схожими типами. Теперь вы можете создавать свои структуры БД, используя полученные знания.

    Создание базы данных в MySQL

    Выбор типа данных для строк/текста (char vs varchar vs text)¶

    В PostgreSQL есть три типа данных для хранения текстовой информации:

    • character(n), char(n) — текст фиксированной длины (строка всегда имеет строго заданный размер)
    • character varying(n), varchar(n) — текст с ограничением по длине (максимальная длина строка может быть ограничена)
    • text — текст неограниченной длины

    Физически максимальный размер любых строк в PostgreSQL ограничен одним гигабайтом (1GB).

    Логическое ограничение на максимальный размер строки (char(n), varchar(n), где n — логическое ограничение), задаваемое пользователем для конкретного поля, лимитирует количество символов в строке, а не длину строки в байтах. Поэтому, несмотря на физический лимит на максимальный размер строки в 1GB, реальное максимальное количество символов в строке может быть меньше, так как различные кодировки символов могут использовать больше одного байта для представления одного символа.

    CHAR(N)

    Этот тип всегда имеет ограничение по длине. Даже, если длина не задана (char), то подразумевается, что она равна единице, то есть char ~ char(1).

    Тип имеет одну особенность, которая выделяет есть среди других текстовых типов. Так как поля с этим типом имеют фиксированный размер (не больше / не меньше заданного), то, при сохранении в таблицу у всех строк, длина которых меньше этого размера, оставшееся пустое место в конце строки заполняется пробелами. Поэтому при сохранении значения ‘123’ в поле с типом char(6) в таблицу реально сохранится ‘123___’. Это может стать неприятным сюрпризом.

    При операциях сравнения полей с типом char(n) пробелы в конце строки игнорируются.

    denis=# SELECT '123 '::char(6) = '123'; ?column? ---------- t (1 row) 

    VARCHAR

    Тип без заданной длины интерпретируется PostgreSQL, как безразмерная строка эквивалентная типу text. При попытке записать в текстовое поле ограниченной длины значение, которое превышает заданные размеры, генерируется ошибка. Строка этого типа хранится в базе данных без изменений (в отличии от char(n)), поэтому нагрузка на процессор при обработке varchar-строк немного меньше, чем при работе с char(n).

    TEXT

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

    Тип text является специфическим типом PostgreSQL, поэтому при разработке приложений для работы с разными СУБД, лучше использовать безразмерный varchar для лучшей переносимости бизнес-логики.

    Резюме¶

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

    Для хранения строк довольно комфортным выбором будет тип varchar без ограничения по длине (если нет жесткого условия, которое не в коем случае нельзя нарушить). Тип char имеет ряд специфических особенностей, которые в большинстве случаев будут только мешать при работе с базой данных. Тип text является специфическим для PostrgeSQL и не имеет никаких преимуществ/недостатком перед типом varchar без ограничения по длине.

    Какое максимальное количество символов может хранить переменная типа char

    Таблица 8.4. Символьные типы

    Имя Описание
    character varying( n ) , varchar( n ) строка ограниченной переменной длины
    character( n ) , char( n ) строка фиксированной длины, дополненная пробелами
    text строка неограниченной переменной длины

    В Таблице 8.4 перечислены символьные типы общего назначения, доступные в Postgres Pro .

    SQL определяет два основных символьных типа: character varying( n ) и character( n ) , где n — положительное число. Оба эти типа могут хранить текстовые строки длиной до n символов (не байт). Попытка сохранить в столбце такого типа более длинную строку приведёт к ошибке, если только все лишние символы не являются пробелами (тогда они будут усечены до максимально допустимой длины). (Это несколько странное исключение продиктовано стандартом SQL .) Если длина сохраняемой строки оказывается меньше объявленной, значения типа character будут дополнятся пробелами; а тип character varying просто сохранит короткую строку.

    При попытке явно привести значение к типу character varying( n ) или character( n ) , часть строки, выходящая за границу в n символов, удаляется, не вызывая ошибки. (Это также продиктовано стандартом SQL .)

    Записи varchar( n ) и char( n ) являются синонимами character varying( n ) и character( n ) соответственно. Если n задано, оно должно быть больше нуля и меньше или равно 10485760. Записи character без указания длины соответствует character(1) . Если же длина не указывается для character varying , этот тип будет принимать строки любого размера. Это поведение является расширением Postgres Pro .

    Помимо этого, Postgres Pro предлагает тип text , в котором можно хранить строки произвольной длины. Хотя тип text не описан в стандарте SQL , его поддерживают и некоторые другие СУБД SQL.

    Значения типа character физически дополняются пробелами до n символов и хранятся, а затем отображаются в таком виде. Однако при сравнении двух значений типа character дополняющие пробелы считаются незначащими и игнорируются. С правилами сортировки, где пробельные символы являются значащими, это поведение может приводить к неожиданным результатам, например SELECT ‘a ‘::CHAR(2) collate «C» < E'a\n'::CHAR(2) вернёт true (условие будет истинным), хотя в локали C символ пробела считается больше символа новой строки. При приведении значения character к другому символьному типу дополняющие пробелы отбрасываются. Заметьте, что эти пробелы несут смысловую нагрузку в типах character varying и text и в проверках по шаблонам, то есть в LIKE и регулярных выражениях.

    Какие именно символы можно сохранить в этих типах данных, зависит от того, какой набор символов был выбран при создании базы данных. Однако символ с кодом 0 (иногда называемый NUL) сохранить нельзя, вне зависимости от выбранного набора символов. За подробностями обратитесь к Разделу 22.3.

    Для хранения короткой строки (до 126 байт) требуется дополнительный 1 байт плюс размер самой строки, включая дополняющие пробелы для типа character . Для строк длиннее требуется не 1, а 4 дополнительных байта. Система может автоматически сжимать длинные строки, так что физический размер на диске может быть меньше. Очень длинные текстовые строки переносятся в отдельные таблицы, чтобы они не замедляли работу с другими столбцами. В любом случае максимально возможный размер строки составляет около 1 ГБ. (Допустимое значение n в объявлении типа данных меньше этого числа. Это объясняется тем, что в зависимости от кодировки каждый символ может занимать несколько байт. Если вы желаете сохранять строки без определённого предела длины, используйте типы text или character varying без указания длины, а не задавайте какое-либо большое максимальное значение.)

    Подсказка

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

    За информацией о синтаксисе строковых констант обратитесь к Подразделу 4.1.2.1, а об имеющихся операторах и функциях вы можете узнать в Главе 9.

    Пример 8.1. Использование символьных типов

    CREATE TABLE test1 (a character(4)); INSERT INTO test1 VALUES ('ok'); SELECT a, char_length(a) FROM test1; -- (1) a | char_length ------+------------- ok | 2 CREATE TABLE test2 (b varchar(5)); INSERT INTO test2 VALUES ('ok'); INSERT INTO test2 VALUES ('good '); INSERT INTO test2 VALUES ('too long'); ОШИБКА: значение не умещается в тип character varying(5) INSERT INTO test2 VALUES ('too long'::varchar(5)); -- явное усечение SELECT b, char_length(b) FROM test2; b | char_length -------+------------- ok | 2 good | 5 too l | 5 

    В Postgres Pro есть ещё два символьных типа фиксированной длины, приведённые в Таблице 8.5. Тип name создан только для хранения идентификаторов во внутренних системных таблицах и не предназначен для обычного применения пользователями. В настоящее время его длина составляет 64 байта (63 ASCII-символа плюс конечный знак), но в исходном коде C она задаётся константой NAMEDATALEN . Эта константа определяется во время компиляции (и её можно менять в особых случаях), а кроме того, максимальная длина по умолчанию может быть увеличена в следующих версиях. Тип «char» (обратите внимание на кавычки) отличается от char(1) тем, что он фактически хранится в одном байте. Он используется во внутренних системных таблицах для простых перечислений.

    Таблица 8.5. Специальные символьные типы

    Имя Размер Описание
    «char» 1 байт внутренний однобайтный тип
    name 64 байта внутренний тип для имён объектов
    Пред. Наверх След.
    8.2. Денежные типы Начало 8.4. Двоичные типы данных

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *