Что быстрее: char(1) или tinyint(1)? Зачем?
МОЯ ПЛАТФОРМА:
PHP и MySQL
МОЯ СИТУАЦИЯ:
Я столкнулся с ситуацией, когда мне нужно сохранить значение для выбора пользователя в одном из моих столбцов таблицы. Теперь мои варианты будут:
- Либо объявите столбец как char(1) и сохраните значение как "y" или "n"
- Или объявите Столбец как tinyint(1) и сохраните значение как 1 или 0
- Этот столбец, объявленный таким образом, также может быть проиндексирован для использования в приложении.
МОИ ВОПРОСЫ:
Итак, я хотел знать, какой из двух указанных выше типов:
Привод к более быстрой скорости запросов при доступе к этому столбцу (для простоты давайте не будем смешивать другие запросы или обращаться к другим столбцам, пожалуйста).
Является ли самый эффективный способ хранения и доступа к данным и почему?
Как меняется скорость доступа, если столбцы индексируются, а когда нет?
Насколько я понимаю, поскольку char(1) и tinyint(1) занимают только 1 байт, в этом случае не будет проблем с объемом памяти. Тогда то, что останется, это скорость доступа. Насколько я знаю, числовая индексация быстрее и эффективнее, чем что-либо еще. Но дело здесь трудно решить, я думаю. Определенно хотел бы услышать ваш опыт по этому вопросу.
Заранее спасибо.
8 ответов
Я думаю, что вы должны создать столбец с ENUM('n','y')
, Mysql хранит этот тип оптимальным образом. Это также поможет вам хранить только допустимые значения в поле.
Вы также можете сделать его более дружелюбным к человеку ENUM('no','yes')
без влияния на производительность. Потому что строки 'no'
а также 'yes'
хранятся только один раз за ENUM
определение. Mysql хранит только индекс значения в строке.
Также обратите внимание на сортировку по ENUM
колонка:
Значения ENUM сортируются в соответствии с порядком, в котором элементы перечисления перечислены в спецификации столбца. (Другими словами, значения ENUM сортируются в соответствии с их порядковыми номерами.) Например, "a" сортирует перед "b" для ENUM("a", "b"), но "b" сортирует перед "a" для ENUM("б", "а").
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
, Код можно найти здесь
Использование 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) и кажется гораздо более знакомым с вычислительной точки зрения, в которой 0 и 1 являются стандартными флагами включения / выключения. Таким образом, хранилище для целых чисел кажется лучше, оно приятнее и его проще использовать в логике кода. 0/1 - явный победитель для меня.
Вы также можете заметить, что, в некоторой степени, это официальная позиция MySQL также из их документации:
BOOL, BOOLEAN: Эти типы являются синонимами для TINYINT(1). Нулевое значение считается ложным. Ненулевые значения считаются истинными.
Если MySQL отождествляет TINYINT (1) с BOOLEAN, это похоже на путь.
Чтобы знать это наверняка, вы должны сравнить его. Или знайте, что это, вероятно, не будет иметь большого значения в более широком представлении всего проекта.
Столбцы Char имеют кодировки и сопоставления, и их сравнение может потребовать ненужных переключений между кодировками, поэтому я предполагаю, что int будет быстрее. По той же причине, я думаю, что обновление индекса для столбца int также происходит быстрее. Но опять же, это не будет иметь большого значения.
CHAR
может занимать более одного байта, в зависимости от выбранного набора символов и параметров таблицы. Некоторые символы могут занимать три байта для кодирования, поэтому MySQL иногда резервирует это пространство, даже если вы используете только y
а также n
,
Они оба будут настолько близки, что это не имеет значения. Если вы чувствуете необходимость задать этот вопрос на SO, вы чрезмерно оптимизируете. Используйте тот, который имеет наиболее логичный смысл.
Хотя я догадываюсь, что индекс в TINYINT будет быстрее, чем индекс в CHAR(1) из-за того, что нет затрат на обработку строк (сортировка, пробелы и т. Д.), У меня нет никаких фактов, чтобы поддержи это. Я думаю, что нет существенной разницы в производительности, о которой стоит беспокоиться.
Однако, поскольку вы используете PHP, сохранение в виде TINYINT имеет гораздо больше смысла. Использование значений 1/0 эквивалентно использованию true
а также false
, даже когда они возвращаются как строки в PHP, и могут быть обработаны как таковые. Вы можете просто сделать if ($record['field'])
с вашими результатами в виде логической проверки, вместо того, чтобы постоянно конвертировать между 'y' и 'n'.
Если вы укажете типы BOOL
или же BOOLEAN
как тип столбца при создании таблицы в MySQL, он создает тип столбца как TINYINT(1)
, Предположительно, это быстрее из двух.
Также:
Мы намерены реализовать полную обработку булевых типов в соответствии со стандартным SQL в будущем выпуске MySQL.
TINYINT 1 Byte
CHAR(M) M Bytes, 0 <= M <= 255
есть ли другое?