Типы данных в MySQL (сжатый справочник для PHP программиста)
Что и как и как много хранит MySQL?
Данный материал создан специально для программистов, которые быстро смогут определиться какой тип данных лучше выбрать для хранения значений в БД MySQL.
Для затравки, интересная цитата из мануала по MySQL:
«Максимальный размер записи в MyISAM составляет 65534 байтов. Каждый BLOB или TEXT-столбец засчитывается здесь как 5-9 байтов.» — как это трактовать однозначно не понятно. НО ясно что много-примного столбцов в таблицу на засунешь. «Извращенистые программисты» — будьте аккуратны (66000 столбцов вы точно создать не сможете).
UPD: Если найдете ошибку, или я что-то где-то утаил — отпишитесь в комментах, с удовольствием добавлю.
UPD1 В первую очередь (и самый лучший вариант для новичков) прочитать ОФИЦИАЛЬНЫЙ МАНУАЛ dev.mysql.com/doc/refman/5.0/en/data-types.html (спасибо Psyh за прямую ссылку), а здесь вырезка для META обработчиков данных (как в лице программистов так и в лице машинной обработки).
UPD2 В принципе, все что написано ниже, можно прочитать по адресу www.mysql.ru/docs/man/Column_types.html (за ссылку «русского перевода», спасибо artuska).
UPD3 Еще одну неплохую ссылку предоставил 4all: newcontinent.ru/h/mysqlc (материал на русском)
UPD4 Цитата из комментов от egorF:
# 14«Как главный редактор русскоязычного перевода доки на MySQL, я рекомендую в него не заглядывать — он уже сказочно морально устарел.»
Следующий массив вполне понятен PHP программистам.
Да и вообще, любые уважающие себя программисты это поймут.
Например:
‘int’=>Array(‘byte’=>4, ‘min’=>-2147483648, ‘max’=>2147483647, ‘umin’=>0, ‘umax’=>4294967295),
Используется так:
Мне надо сохранить в поле максимальное числовое значение 234 259 000 000 000.
INT — для этого не подходит. Смотрим другие типы и находим, что BIGINT вполне подойдет.
$MYSQL_TYPES=Array(
// INTEGER
// byte — кол-во байт на хранение,
// max/min — предельные значения,
// umax/umin — беззнаковые предельные значения
‘int’ =>Array( ‘byte’ =>4, ‘min’ =>-2147483648, ‘max’ =>2147483647, ‘umin’ =>0, ‘umax’ =>4294967295),
‘bigint’ =>Array( ‘byte’ =>8, ‘min’ =>-9223372036854775808, ‘max’ =>9223372036854775807, ‘umin’ =>0, ‘umax’ =>18446744073709551615),
‘tinyint’ =>Array( ‘byte’ =>1, ‘min’ =>-128, ‘max’ =>127, ‘umin’ =>0, ‘umax’ =>255),
‘smallint’ =>Array( ‘byte’ =>2, ‘min’ =>-32768, ‘max’ =>32767, ‘umin’ =>0, ‘umax’ =>65535),
‘mediumint’ =>Array( ‘byte’ =>3, ‘min’ =>-8388608, ‘max’ =>8388607, ‘umin’ =>0, ‘umax’ =>16777215),
// FLOAT DOUBLE
// Внимание! Не храните денежные значения в этих полях. Деньги надо хранить — в DECIMAL
// у FLOAT ТОЧНОСТЬ ТОЛЬКО 7 ЦИФР. (все остальные цифры «смазываются»)
// у DOUBLE ТОЧНОСТЬ ТОЛЬКО 15 ЦИФР. (все остальные цифры «смазываются»)
// byte — кол-во байт для хранения поля (по-умолчанию)
// max_byte — максимальное кол-во байт для хранения
// negative_min/negative_max — минмаксы для отрицательных чисел
// positive_min/positive_max — минмаксы для положительных чисел
‘float’ =>Array( ‘byte’ =>4, ‘max_byte’ =>8, ‘negative_min’ =>-3.402823466E+38, ‘negative_max’ =>-1.175494351E-38, ‘positive_min’ =>1.175494351E-38, ‘positive_max’ =>3.402823466E+38),
‘double’ =>Array( ‘byte’ =>8, ‘negative_min’ =>-1.7976931348623157E+308, ‘negative_max’ =>-2.2250738585072014E-308, ‘positive_min’ =>2.2250738585072014E-308, ‘positive_max’ =>1.7976931348623157E+308),
// BOOLEAN
// сами все поймете
‘bool’ =>Array( ‘byte’ =>1, ‘true’ =>1, ‘false’ =>0),
‘boolean’ =>Array( ‘byte’ =>1, ‘true’ =>1, ‘false’ =>0),
// VARCHAR
// byte — кол-во байт отведенных для хранения (можно задать меньше)
// min_byte — минимальное кол-во байт в которых может храниться поле (если длина равна 1)
// В MYSQL 5.0.3 и выше, VARCHAR может быть до 65,535 символов.
// length — максимальная длина символов в поле
‘varchar’ =>Array( ‘byte’ =>256, ‘min_byte’ =>2, ‘length’ =>255),
‘char’ =>Array( ‘byte’ =>256, ‘min_byte’ =>2, ‘length’ =>255),
// TEXT
// byte — кол-во байт для хранения поля
// min_byte — минимальное кол-во байт для хранения одного символа (если длина поля равна 1)
// length — максимальное количество символов в поле
‘tinytext’ =>Array( ‘byte’ =>256, ‘min_byte’ =>2, ‘length’ =>255),
‘text’ =>Array( ‘byte’ =>65537, ‘min_byte’ =>3, ‘length’ =>65535),
‘mediumtext’ =>Array( ‘byte’ =>16777218, ‘min_byte’ =>4, ‘length’ =>16777215),
‘longtext’ =>Array( ‘byte’ =>4294967300, ‘min_byte’ =>5, ‘length’ =>4294967296),
‘tinyblob’ =>Array( ‘byte’ =>256, ‘min_byte’ =>2, ‘length’ =>255),
‘blob’ =>Array( ‘byte’ =>65537, ‘min_byte’ =>3, ‘length’ =>65535),
‘mediumblob’ =>Array( ‘byte’ =>16777219, ‘min_byte’ =>4, ‘length’ =>16777215),
‘longblob’ =>Array( ‘byte’ =>4294967300, ‘min_byte’ =>5, ‘length’ =>4294967296),
Типы данных MySQL. Чем руководствоваться при выборе типа данных
Опубликовано: 23 Апреля 2019
Выбирая тип данных для столбца, прежде всего стоит определить общий класс данных, который лучше использовать для столбца: числовые, строковые или временные;
Далее необходимо выбрать конкретный тип данных из представленных в классе. Многие типы данных MySQL позволяют хранить данные одного и тот же вида, но с разным диапазоном значений, точностью или требуемым физическим пространством (на диске или в памяти). Некоторые типы обладают специальным поведением или свойствами.
Например, в столбцах DATETIME и TIMESTAMP можно хранить один и тот же тип данных: дату и время, с точностью до секунды. Однако тип TIMESTAMP требует вдвое меньше места, позволяет работать с часовыми поясами и обладает специальными средствами автоматического обновления. С другой стороны, диапазон допустимых значений для него намного уже.
На что обратить внимание при выборе типа данных:
Скорость при соединении столбцов типа VARCHAR и ENUM:
Соединение VARCHAR с VARCHAR
Соединение VARCHAR с ENUM
Соединение ENUM с VARCHAR
Соединение ENUM с ENUM
В целях совместимости MySQL поддерживает различные псевдонимы, например INTEGER, BOOL — это псевдонимы (синонимы) одного и того же типа данных. Данный факт может сбить с толку, но не оказывает влияния на производительность.
Числовые типы
Хранение целых чисел
СУБД MySQL позволяет указывать для целых чисел «размер», например INT(11). Для большинства приложений это не имеет значения: диапазон возможных значений этим не ограничивается. Однако данный параметр говорит некоторым интерактивным инструментам MySQL, сколько позиций необходимо зарезервировать для вывода числа. С точки зрения хранения и вычисления INT(1) и INT(20) идентичны.
Знаковые и беззнаковые типы требуют одинакового пространства и обладают одинаковой производительностью.
Необязательный атрибут ZEROFILL заполнит нулями свободные позиции слева. Например с TINYINT(3) ZEROFILL, величина 2 будет записана, как 002.
| Тип данных | Бит | По умолчанию | UNSIGNED |
|---|---|---|---|
| TINYINT | 8 | -128 — 127 | 0 — 255 |
| SMALLINT | 16 | -32768 — 32767 | 0 — 65535 |
| MEDIUMINT | 24 | -8388608 — 8388607 | 0 — 16777215 |
| INT | 32 | -2147483648 — 2147483647 | 0 — 4294967295 |
| BIGINT | 64 | -9223372036854775808 — 9223372036854775807 | 0 — 18446744073709551615 |
Хранение дробных чисел
Все типы допускают приближенные математические вычисления с плавающей точкой, но в случае с FLOAT и DOUBLE операции выполняются быстрее, так как процессор выполняет их естественным для него образом.
M — количество отводимых под число символов. D — количество символов дробной части.
Для типов с плавающей точкой можно указать максимально разрешенное количество цифр до и после десятичной запятой. В случае с DECIMAL это влияет на объем пространства, требуемого для хранения данных столбца. При указании точности, в некоторых случаях, MySQL незаметно для пользователя может выбирать другой тип данных или будет округлять значения при сохранении. Поэтому рекомендуют указывать желаемый тип, но не точность.
FLOAT и DOUBLE могут иметь параметр UNSIGNED, запрещающий отрицательные числа, но диапазон значений от этого не изменится.
Число типа DECIMAL в MySQL 5.0 и более новых версиях может содержать до 65 цифр. В более ранних версиях MySQL тип DECIMAL имел предел 254 цифры и хранил значения в виде неупакованных строк (один байт на цифру). Однако эти версии СУБД не умели использовать такие большие числа в вычислениях, поскольку тип DECIMAL был просто форматом хранения. При выполнении каких-либо операций значения DECIMAL преобразовывались в тип DOUBLE.
Строковые типы
В типах CHAR и VARCHAR строки рассматриваются как последовательности символов, поэтому, при использовании многобайтных кодировок, например UNICODE, размер строки в байтах будет больше, чем в символах.
При создании таблицы нельзя комбинировать столбцы типов CHAR и VARCHAR. Если такое произойдет, то MySQL изменит тип столбцов CHAR на тип VARCHAR.
Представим что строковый тип применяется для хранения значений Y и N. В случае использования CHAR(1) значение займет один байт, тогда как для типа VARCHAR(1) потребуется два байта из-за наличия дополнительного байта длины строки.
| Значение | CHAR(4) | Требуется хранилище | VARCHAR(4) | Требуется хранилище |
|---|---|---|---|---|
| » | ‘ ‘ | 4 байта | » | 1 байт |
| ‘ab’ | ‘ab ‘ | 4 байта | ‘ab’ | 3 байта |
| ‘abcd’ | ‘abcd’ | 4 байта | ‘abcd’ | 5 байт |
| ‘abcdefgh’ | ‘abcd’ | 4 байта | ‘abcd’ | 5 байт |
Двоичные строки
Для совместимости со старыми версиями MySQL введены два специальных типа данных: BINARY и VARBINARY, которые эквивалентны типам CHAR и VARHAR, однако строка в них рассматривается как последовательность байтов, а не символов. К BINARY строкам не применимы кодировки и сортируются они как обычные последовательности байтов. Эти типы могут быть полезны, когда нужно сохранять двоичные данные, и вы хотите, чтобы MySQL сравнивал значение как байты, а не как символы. При этом, двоичное сравнение может оказаться значительно проще и быстрее символьного.
Текстовые и бинарные типы
Предназначены для хранения больших объемов двоичных или символьных данных.
MySQL обрабатывает значения BLOB и TEXT как отдельные объекты. Единственное различие между семействами BLOB и TEXT заключается в том, что типы BLOB хранят двоичные данные без учета схемы упорядочения и кодировки, а с типами TEXT ассоциированы схемы упорядочения и кодировка.
Семейство TEXT используется для хранения непосредственно текста:
Cемейство BLOB — для хранения изображений, звука, электронных документов и т.д.:
MySQL не может индексировать данные этих типов по полной длине и не может использовать для сортировки индексы.
Подсистема хранения Memory не поддерживает типы BLOB и TEXT.
PHP Profi
Квест → Как хакнуть форму
Типы данных в PHP и MySQL Перевод
С тех пор как был выпущен PHP 7.0, большое внимание уделяется скалярным типам. Сохранять типы данных внутри вашего приложения теперь довольно просто. Но когда речь идёт о внешних системах, таких как база данных, то всё не так всё гладко, как казалось изначально.
В случае с MySQL типы, с которыми мы работаем, в первом приближении, определены сетевым протоколом. Сетевой протокол MySQL по умолчанию преобразует все данные в строки. Так что если мы возьмём целое число из базы данных и будем использовать типизацию в PHP 7, мы получим ошибку:
Конечно, есть простое решение: либо преобразовать самим, либо отключить строгий режим и PHP преобразует за нас.
Теперь давайте взглянем на другой случай. Предположим у нас есть приложение, где мы получаем целочисленный ID из базы данных. Мы знаем, что MySQL отправит нам строку, и мы относимся к ID как к непрозрачным данным в любом случае, таким образом у нас есть проверка типа на строку. Сейчас мы немного отрефакторим код и будем использовать подготовленные запросы (prepared statements). Какой будет результат?
Постойте! Что там случилось?! Разве я только что не говорил, что протокол MySQL всегда будет отправлять строку, таким образом, мы получаем строку в PHP?! Да говорил, и это верно для «прямых запросов». Но это не так для подготовленных запросов. С готовыми запросами протокол MySQL использует двоичное кодирование данных и поэтому mysqlnd и mysqli будут пытаться найти соответствующий тип PHP. Это не всегда возможно, особенно если мы наталкиваемся на диапазон больших значений. Итак, давайте сделаем запрос для PHP_INT_MAX и PHP_INT_MAX+1 и посмотрим на типы:
Подобные вещи происходят и в других типах, которые не могут быть правильно представлены в PHP:
Итак, подведём итог:
Теперь мы можем ожидать того же при использовании PDO. Давайте проверим:
Этот пример использует подготовленные запросы, но возвращает строки?! Причина в том, что PDO по умолчанию не использует подготовленные запросы на сетевом уровне, а эмулирует на уровне PHP. Это означает, что PHP заменяет плейсхолдеры в шаблоне запроса, а затем выполняется прямой запрос. Как упоминалось выше, для прямых запросов MySQL-сервер отправляет строки, так что PHP воспринимает все данные как строки. Однако мы можем легко попросить PDO отключить эмуляцию:
Но остаётся вопрос, нужно ли отключать эмуляцию для того, чтобы получить правильные типы? Т.к. это влияет на производительность. С родной подготовкой запросов клиент-серверный обмен данными будет происходить во время подготовки и еще один обмен — при выполнении запроса. С эмуляцией — только во время выполнения. Родная подготовка запросов также требует некоторые ресурсы сервера для сохранения данных. Однако если один запрос выполняется несколько раз, возможна некоторая экономия. Также представление типов означает, что происходят различные преобразования типов и различное количество и точность данных передается. В большинстве случаев это не должно иметь существенного влияния, но в итоге покажет только тест.
Надеюсь, что это поможет дать лучшее понимание, а может ещё больше запутает.
Типы данных в MySQL
При создании структуры базы данных крайне важно правильно подобрать типы данных в MySQL чтобы избежать проблем в будущем. Примером такой проблемы является переполнение отведённого диапазона значений, что повлекло за собой потерю данных.
Проблема переполнения не единственная, при не оправданном использовании более рессурсоёмких типов снижается производительность всей базы.
Типы данных в MySQL
Все типы в MySQL можно разделить 4 группы:
Атрибуты в MySQL
Сравнение в MySQL
Основной особенностью в данной характеристики является следующее: для сравнения …_bin важен регистр введённых значений, то есть строки «Текст» и «текст» являются разными! Для других характеристик сравнения данные строки будут одинаковыми.
Чаще всего …_bin используется для авторизации, при сравнении логина и пароля.
Индексы в MySQL
Индексы в MySQL – позволяют ускорить выборку данных из базы.
Мы можем создать индекс для любого поля таблицы, но рекомендуется добавлять индексы лишь тем полям, которые часто попадают в WHERE.
SELECT * FROM `имя таблицы` WHERE title = 1;
В данном случае для поля title рекомендуется создать индекс.
Не стоит добавлять индексы на все поля подряд, так как индекс создаёт дополнительные (служебные) таблицы, что существенно увеличивает общий размер базы!
Виды индексов в MySQL:
PHP 5 Типы данных
Типы данных PHP
Переменные могут хранить данные различных типов, а различные типы данных могут выполнять разные действия.
PHP поддерживает следующие типы данных:
Строка PHP
Строка представляет собой последовательность символов, например «Hello World!».
Строка может быть любым текстом внутри кавычек. Можно использовать одинарные или двойные кавычки:
Пример
Целое число PHP
Правила для целых чисел:
Пример
PHP float
Float (число с плавающей запятой) — это число с десятичной запятой или числом в экспоненциальной форме.
Пример
Логическое значение PHP
Логическое значение представляет два возможных состояния: true или false.
Логические значения часто используются в условном тестировании. Подробнее об условном тестировании вы узнаете в следующей главе этого учебного пособия.
Массив PHP
Массив хранит несколько значений в одной переменной.
Пример
Вы узнаете намного больше о массивах в последующих главах этого учебного пособия.
Объект PHP
Объект — это тип данных, который хранит данные и информацию о том, как обрабатывать эти данные.
В PHP объект должен быть объявлен явным образом.
Сначала мы должны объявить класс Object. Для этого мы используем ключевое слово Class. Класс — это структура, которая может содержать свойства и методы:
Пример
// create an object
$herbie = new Car();
Значение NULL PHP
NULL — это специальный тип данных, который может иметь только одно значение: NULL.
Переменная типа данных NULL — это переменная, которой не назначено значение.
Совет: Если переменная создается без значения, ей автоматически присваивается значение null.
Переменные также могут быть очищены, установив значение NULL:
Пример
Ресурс PHP
Тип специального ресурса не является фактическим типом данных. Это хранение ссылки на функции и ресурсы, внешние для PHP.
Распространенным примером использования типа данных Resource является вызов базы данных.
Мы не будем говорить о типе ресурса здесь, так как это продвинутая тема.