Я использую MySQL 8.0 CE. У меня есть атрибут, в котором я хочу сохранить статус TRUE или FALSE, и я хочу, чтобы он занимал как можно меньше места.
Прочитав ответы на этот вопрос: MySQL: Наименьший тип данных для одного бита и документация MySQL Тип битового значения - BIT и Целочисленные типы (точное значение), я понимаю, что на уровне хранения лучше использовать BIT(1) потому что BOOL на самом деле является TINYINT(1) и поэтому использует полный 1 байт.
На уровне хранилища ясно, что BIT(1) — лучший вариант, но на уровне производительности при поиске истинного или ложного?
Если я правильно понимаю, BIT будет хранить 1 или 0, а BOOL хранит TRUE или FALSE.
Эта разница заключается в том, что при поиске между обеими возможностями один из типов лучше оптимизирован для этого?
Спасибо.
Что ты имеешь в виду?
@SideTest — Девлин имеет в виду обычную практику программистов, которые заранее тратят время на оптимизацию вещей, которые не будут иметь достаточного значения, чтобы оправдать потраченное время.
@devlincarnate - А, хорошо! Да! это возможно. Но я люблю докапываться до сути, даже если потом не использую :) К тому же, это действительно хобби, так что время относительно. В реальной жизни со сроками я бы не смог сделать так много, хотя правда и то, что я люблю максимально оптимизировать вещи.
BIT(1)
также требует минимум 1 байт, поэтому вы не экономите место по сравнению с BOOL
/TINYINT
. Оба занимают 1 байт.
Говоря с разработчиками MySQL, они обычно вздрагивают, когда я упоминаю тип данных BIT
. Он полон известных ошибок и, вероятно, не обнаруженных ошибок. Внутренний код плохо изучен. Они сказали мне просто использовать TINYINT
.
Кстати, в MySQL нет настоящего BOOL
типа. BOOL
— это просто псевдоним для TINYINT(1)
, и нет истинного или ложного значения. Значение «ложь» — это буквально целое число 0, а значение «истина» — это целое число 1. Другими словами, вы можете SUM()
столбец, который предположительно является логическим, и вы получите целочисленную сумму, равную количеству строк, в которых столбец "истинный". Это несовместимо со стандартным SQL (нет смысла использовать SUM() для логического столбца), но именно так BOOL
реализовано в MySQL.
В другом направлении NULL
действует как ложь, и любое ненулевое значение является «истиной».
@RickJames Я бы не сказал, что NULL
ложно, потому что NOT NULL
неправда.
Какая логика в существовании BIT(1)
, BOOL
/TINYINT(1)
, если все они занимают 1 байт? В любом случае, видя, что все они занимают одно и то же место и что, как говорит @RickJames, нет заметного улучшения производительности, я выслушаю вас и воспользуюсь TINYINT(1)
.
@SideTest, MySQL реализует строковый тип данных BIT
как часть стандарта SQL, поэтому клиенты ожидают, что он будет поддерживаться. Если вы храните более длинные битовые строки, они эффективно используют байты. Но они выделяют целый байт за раз. Таким образом, строка из N
бит использует (N+7)/8
байт.
Вы имеете в виду, что в стандарте SQL BIT(1)
будет занимать только 1 бит, а не байт? Другое дело, что потом он будет сгруппирован по байтам.
Нет, в стандарте указано только, что BIT
— это тип данных, семантика которого позволяет вызывающей стороне адресовать отдельные биты. Это не диктует, как это должно храниться. Я говорю о том, как это реализует MySQL.
Учитывая, что в mysql логическое значение такое же, как и tinyint(1). Тем не менее, логическое значение всегда использует 1 байт на столбец, но бит (n) будет использовать столько байтов, сколько необходимо для хранения заданного количества битов. BIT экономит место, однако я бы использовал логическое значение, потому что оно упрощает работу в тот момент, когда вы хотите запросить базу данных. в терминах вы можете иметь значения, отличные от 0 или 1, если вы не будете осторожны. Чтобы избежать этого, вы можете использовать псевдонимы TRUE и FALSE.
(В дополнение к тому, что говорит Билл...)
У меня есть практическое правило: «Если предварительная оценка не предполагает улучшения хотя бы на 10%, перейдите к какой-либо другой оптимизации». Соедините это с тем фактом, что даже если однобитовое логическое значение сократит длину строки на 7 бит, это, вероятно, даст экономию менее 1%. Итак, я иду дальше.
OTOH, если у вас много логических значений, рассмотрите тип данных SET
, который может обрабатывать до 64 логических значений в 8 байтах или меньше. Но это довольно неуклюже. То же самое и с 64-битным BIGINT UNSIGNED
вместе со сдвигом и логическими операторами (<<
, &
и т. д.).
Если вам нужно INDEX
одно или несколько логических значений, забудьте об этом. Единственный случай, когда индексирование работает, — это составной (многостолбцовый) индекс, где один из столбцов [эффективно] TINYINT NOT NULL
Да, я тоже смотрел на тип set
и рассмотрю его в будущем, но для этого случая мне просто нужны два варианта.
@SideTest - Похоже на мои правила RoT.
Это пахнет преждевременной оптимизацией