Что быстрее: char (1) или tinyint (1)? Зачем?
МОЯ ПЛАТФОРМА:
PHP и mySQL
МОЯ СИТУАЦИЯ:
Я столкнулся с ситуацией, когда мне нужно сохранить значение для выбора пользователя в одном из моих столбцов таблицы. Теперь мои варианты:
- Объявите столбец как char (1) и сохраните значение как 'y' или 'n'
- Или объявите столбец как tinyint (1) и сохраните значение как 1 или 0
- Этот объявленный столбцом также может быть проиндексирован для использования в приложении.
МОИ ВОПРОСЫ:
Итак, я хотел знать, какой из этих двух типов:
-
Приводит к более быстрой скорости запроса при доступе к этому столбцу (для простоты, оставьте без смешивания другие запросы или доступ к другим столбцам, пожалуйста).
-
Является наиболее эффективным способом хранения и доступа к данным и почему?
-
Как скорость доступа меняется, если столбцы индексируются, а когда нет?
Я понимаю, что, поскольку char (1) и tinyint (1) занимают только 1 байтовое пространство, пространство для хранения в этом случае не будет проблемой. Тогда осталась бы скорость доступа. Насколько мне известно, числовое индексирование быстрее и эффективнее всего.
Но я считаю, что здесь трудно принять решение. Было бы обязательно услышать ваш опыт на этом.
Спасибо заранее.
Ответы
Ответ 1
Я думаю, вы должны создать столбец с ENUM('n','y')
. Mysql сохраняет этот тип оптимальным образом. Это также поможет вам сохранить только допустимые значения в поле.
Вы также можете сделать его более дружественным к человеку ENUM('no','yes')
, не влияя на производительность. Поскольку строки 'no'
и 'yes'
сохраняются только один раз для определения ENUM
. Mysql сохраняет только индекс значения в строке.
Также обратите внимание на сортировку по столбцу ENUM
:
Значения ENUM сортируются в соответствии с порядком, в котором перечисляемые элементы перечислены в спецификации столбца. (Другими словами, значения ENUM сортируются в соответствии с их номерами индексов.) Например, 'a' сортирует перед 'b' для ENUM ('a', 'b'), но 'b' сортирует перед 'a' для ENUM ('b', 'a').
Ответ 2
Rate insert tinyint(1) insert char(1) insert enum('y', 'n')
insert tinyint(1) 207/s -- -1% -20%
insert char(1) 210/s 1% -- -19%
insert enum('y', 'n') 259/s 25% 23% --
Rate insert char(1) insert tinyint(1) insert enum('y', 'n')
insert char(1) 221/s -- -1% -13%
insert tinyint(1) 222/s 1% -- -13%
insert enum('y', 'n') 254/s 15% 14% --
Rate insert tinyint(1) insert char(1) insert enum('y', 'n')
insert tinyint(1) 234/s -- -3% -5%
insert char(1) 242/s 3% -- -2%
insert enum('y', 'n') 248/s 6% 2% --
Rate insert enum('y', 'n') insert tinyint(1) insert char(1)
insert enum('y', 'n') 189/s -- -6% -19%
insert tinyint(1) 201/s 7% -- -14%
insert char(1) 234/s 24% 16% --
Rate insert char(1) insert enum('y', 'n') insert tinyint(1)
insert char(1) 204/s -- -4% -8%
insert enum('y', 'n') 213/s 4% -- -4%
insert tinyint(1) 222/s 9% 4% --
кажется, что, по большей части, enum('y', 'n')
быстрее вставлять.
Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1) 188/s -- -7% -8%
select tinyint(1) 203/s 8% -- -1%
select enum('y', 'n') 204/s 9% 1% --
Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1) 178/s -- -25% -27%
select tinyint(1) 236/s 33% -- -3%
select enum('y', 'n') 244/s 37% 3% --
Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1) 183/s -- -16% -21%
select tinyint(1) 219/s 20% -- -6%
select enum('y', 'n') 233/s 27% 6% --
Rate select tinyint(1) select char(1) select enum('y', 'n')
select tinyint(1) 217/s -- -1% -4%
select char(1) 221/s 1% -- -2%
select enum('y', 'n') 226/s 4% 2% --
Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1) 179/s -- -14% -20%
select tinyint(1) 208/s 17% -- -7%
select enum('y', 'n') 224/s 25% 7% --
Выбор также выглядит как enum
. Код может быть найден здесь
Ответ 3
Использование tinyint является более стандартной практикой и позволит вам более легко проверить значение поля.
// Using tinyint 0 and 1, you can do this:
if($row['admin']) {
// user is admin
}
// Using char y and n, you will have to do this:
if($row['admin'] == 'y') {
// user is admin
}
Я не эксперт в области внутренней работы MySQL, но он интуитивно чувствует, что поиск и сортировка целых полей быстрее, чем поля символов (я просто чувствую, что 'a' > 'z' больше работает, чем 0 > 1), и, похоже, он гораздо более знаком с вычислительной точки зрения, в которой 0s и 1s являются стандартными флагами включения/выключения. Таким образом, хранение целых чисел, по-видимому, лучше, оно приятнее и легче использовать в логике кода. 0/1 - явный победитель для меня.
Вы также можете заметить, что в некоторой степени это официальная позиция MySQL также из их документации:
BOOL, BOOLEAN: Эти типы являются синонимами для TINYINT (1). Значение нуля равно считается ложным. Ненулевые значения считается истинным.
Если MySQL доходит до того, что приравнивает TINYINT (1) к BOOLEAN, это похоже на путь.
Ответ 4
Чтобы это точно знать, вам следует сравнить его. Или знайте, что это, вероятно, не будет иметь большого значения в грандиозном представлении всего проекта.
В столбцах Char есть кодировки и сопоставления, и их сравнение может включать ненужные переключатели между кодировками, поэтому я предполагаю, что int будет быстрее. По той же причине я считаю, что обновление индекса в столбце int также выполняется быстрее. Но опять же, это не имеет большого значения.
CHAR
может занимать более одного байта, в зависимости от выбранного набора символов и параметров таблицы. Некоторые символы могут принимать три байта для кодирования, поэтому MySQL иногда резервирует это пространство, даже если вы используете только y
и n
.
Ответ 5
Они оба будут так близки, что это не имеет значения. Если вы чувствуете, что должны задавать этот вопрос на SO, вы чрезмерно оптимизируете. Используйте то, что наиболее логично.
Ответ 6
Если вы указываете типы BOOL
или BOOLEAN
как тип столбца при создании таблицы в MySQL, он создает тип столбца как TINYINT(1)
. Предположительно это быстрее из двух.
Документация
также:
Мы намерены реализовать полное логическое типа в соответствии с стандартный SQL, в будущем MySQL выпуск.
Ответ 7
В то время как моя догадка заключается в том, что индекс в TINYINT будет быстрее индекса на CHAR (1) из-за того, что нет накладных расходов на обработку строк (сортировка, пробелы и т.д.), У меня есть факты, подтверждающие это. Я предполагаю, что нет существенной разницы в производительности, о которой стоит беспокоиться.
Однако, поскольку вы используете PHP, сохранение в качестве TINYINT имеет больше смысла. Использование значений 1/0 эквивалентно использованию true
и false
, даже если они возвращаются как строки в PHP и могут обрабатываться как таковые. Вы можете просто сделать if ($record['field'])
с вашими результатами в виде булевой проверки, а не конвертировать между "y" и "n" все время.
Ответ 8
TINYINT 1 Byte
CHAR(M) M Bytes, 0 <= M <= 255
есть ли другое?