Что быстрее: char (1) или tinyint (1)? Зачем? - PullRequest
26 голосов
/ 07 января 2010

МОЯ ПЛАТФОРМА:

PHP & MySQL

МОЯ СИТУАЦИЯ:

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

  1. Либо объявите Столбец как char (1) и сохраните значение как 'y' или 'n'
  2. Или объявите Столбец как tinyint (1) и сохраните значение как 1 или 0
  3. Этот столбец, объявленный таким образом, также может быть проиндексирован для использования в приложении.

МОИ ВОПРОСЫ:

Итак, я хотел знать, какой из двух указанных выше типов:

  1. Приводит к более высокой скорости запросов при обращении к этому столбцу (для простоты давайте не будем смешивать другие запросы или обращаться к другим столбцам, пожалуйста).

  2. Является ли самый эффективный способ хранения и доступа к данным и почему?

  3. Как меняется скорость доступа, если столбцы индексируются, а когда нет?

Насколько я понимаю, поскольку char (1) и tinyint (1) занимают только 1 байт, в этом случае объем памяти не будет проблемой. Тогда то, что останется, это скорость доступа. Насколько я знаю, числовое индексирование быстрее и эффективнее, чем все остальное. Но дело здесь трудно решить, я думаю. Определенно хотел бы услышать ваш опыт по этому вопросу.

Заранее спасибо.

Ответы [ 8 ]

36 голосов
/ 08 января 2010
                       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. Код может быть найден здесь

30 голосов
/ 07 января 2010

Я думаю, вы должны создать столбец с ENUM('n','y'). Mysql хранит этот тип оптимальным образом. Это также поможет вам хранить в поле только разрешенные значения.

Вы также можете сделать его более удобным для человека ENUM('no','yes') без ущерба для производительности. Поскольку строки 'no' и 'yes' сохраняются только один раз для определения ENUM. Mysql хранит только индекс значения в строке.

Также обратите внимание на сортировку по столбцу ENUM:

Значения ENUM сортируются в соответствии с порядком, в котором элементы перечисления перечислены в спецификации столбца. (Другими словами, значения ENUM сортируются в соответствии с их индексами.) Например, «a» сортирует перед «b» для ENUM («a», «b»), но «b» сортирует перед «a» для ENUM («б», «а»).

10 голосов
/ 07 января 2010

Использование 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, это похоже на путь.

4 голосов
/ 07 января 2010

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

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

CHAR может занимать более одного байта, в зависимости от выбранного набора символов и параметров таблицы. Некоторые символы могут занимать три байта для кодирования, поэтому MySQL иногда резервирует это пространство, даже если вы используете только y и n.

2 голосов
/ 07 января 2010

Они оба будут настолько близки, что это не имеет значения. Если вы чувствуете необходимость задать этот вопрос на SO, вы чрезмерно оптимизируете. Используйте тот, который имеет наиболее логичный смысл.

1 голос
/ 07 января 2010

Хотя у меня есть догадка, что индекс в TINYINT будет быстрее, чем индекс в CHAR (1) из-за того, что нет никаких затрат на обработку строк (сортировка, пробелы и т. Д.), У меня нет любые факты, подтверждающие это. Я думаю, что нет существенной разницы в производительности, о которой стоит беспокоиться.

Однако, поскольку вы используете PHP, сохранение в виде TINYINT имеет гораздо больше смысла. Использование значений 1/0 эквивалентно использованию true и false, даже если они возвращаются в виде строк в PHP, и может быть обработано как таковое. Вы можете просто сделать if ($record['field']) со своими результатами в качестве логической проверки, вместо того, чтобы постоянно конвертировать между 'y' и 'n'.

1 голос
/ 07 января 2010

Если вы указываете типы BOOL или BOOLEAN в качестве типа столбца при создании таблицы в MySQL, он создает тип столбца как TINYINT(1). Предположительно, это быстрее, чем два.

Документация

Также:

Мы намерены реализовать полный логический тип обработки, в соответствии с стандартный SQL, в будущем MySQL релиз.

0 голосов
/ 07 января 2010
 TINYINT    1 Byte
CHAR(M)     M Bytes, 0 <= M <= 255

есть что-то другое?

...