Следует ли избегать использования среды в mysql?

Я наткнулся на комментарий к следующему блогу, который рекомендует не использовать mediaint:

Не используйте [24-битный INT], даже в MySQL. Его немой, и его медленный, и код, который его реализует, - это ужасный ужас.

4294967295 и MySQL INT (20) Синтаксические удары

Ответ на stackoverflow также отмечает, что SQL Server, Postgres и DB2 не поддерживают среду.

В чем разница между tinyint, smallint, mediumint, bigint и int в MySQL?

Следует ли избегать использования среды или продолжать использовать ее в тех случаях, когда она лучше всего отражает данные, которые я храню?

Ответ 1

InnoDB сохраняет MEDIUMINT в виде трех байтов. Но когда MySQL должен делать какие-либо вычисления, три байта MEDIUMINT преобразуются в восемь байтов unsigned long int (я полагаю, никто не запускает MySQL на 32 бита в настоящее время).

Есть плюсы и минусы, но вы понимаете, что "Его немой, и его медленный, и код, который его реализует, - это обходный ужас", рассуждение не является техническим, не так ли?

Я бы сказал, что MEDIUMINT имеет смысл, когда размер данных на диске имеет решающее значение. Т.е. когда в таблице так много записей, что даже одна байтовая разность (4 байта INT против 3 байт MEDIUMINT) означает много. Это довольно редкий случай, но возможно.

mach_read_from_3 и mach_read_from_4 - примитивы, которые InnoDB использует для чтения чисел из записей InnoDB, схожи. Они оба возвращают ulint. Бьюсь об заклад, вы не заметите разницы в любой рабочей нагрузке.

Просто взгляните на код:

ulint
mach_read_from_3(
/*=============*/
        const byte*     b)      /*!< in: pointer to 3 bytes */
{
        ut_ad(b);
        return( ((ulint)(b[0]) << 16)
                | ((ulint)(b[1]) << 8)
                | (ulint)(b[2])
                );
}

Считаете ли вы, что это намного медленнее, чем это?

ulint
mach_read_from_4(
/*=============*/
        const byte*     b)      /*!< in: pointer to four bytes */
{
        ut_ad(b);
        return( ((ulint)(b[0]) << 24)
                | ((ulint)(b[1]) << 16)
                | ((ulint)(b[2]) << 8)
                | (ulint)(b[3])
                );
}

Ответ 2

В великой схеме вещей выборка - большая стоимость. Простые функции, выражения и, тем более, форматы данных незначительны в том, сколько времени занимает запрос.

С другой стороны, если ваш набор данных слишком велик, чтобы оставаться в кэше, накладные расходы ввода-вывода для получения строк (строк) еще более значительны. Грубое эмпирическое правило гласит, что не кэшированная строка занимает в 10 раз больше, чем кешированная. Следовательно, сжатие набора данных (например, использование меньшего *INT) может дать вам огромное преимущество в производительности.

Этот аргумент яблок ...INT, FLOAT против DOUBLE, DECIMAL(m,n), DATETIME(n) и т.д. (Для [VAR]CHAR/BINARY(...) и TEXT/BLOB требуется другое обсуждение. )

Для тех, кто имеет фон на языке ассемблера...

  • Таблица, вероятно, будет иметь смесь чисел и строк, тем самым препятствуя попыткам "выровнять" значения.
  • MySQL всегда обрабатывал различные аппаратные средства (большие/мало-endian, 16/32/64-бит) с двоичной совместимостью. Обратите внимание на то, как код @akuzminsky предоставил возможность избежать выравнивания и устранения ошибок. И это позволяет компилятору иметь дело с 32-разрядными проблемами, если аппаратное обеспечение составляет всего 16 бит.
  • Код для проверки для особых случаев, вероятно, перевешивает просто пишущий общий код.
  • Мы говорим, как правило, менее 1% от общего времени обработки строк.

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

Для оптимизации в порядке важности:

  1. Подсчитайте диски. Прикосновение к диску в подавляющем большинстве является самой дорогостоящей частью запроса.
  2. Подсчитайте количество затронутых строк. Поиск строки (через BTree и т.д.) Занимает некоторый процессор. Но, заметьте, очень мало установок связаны с CPU; те, которые имеют тенденцию иметь плохие показатели. (Правило большого пальца: обычно в строке индекса или индекса индекса InnoDB содержится 100 строк).
  3. Только теперь разбор строки входит в игру.

Правило большого пальца: если предварительная оптимизация не позволяет (с помощью огибающей конверта) получить 10% -ное улучшение, не тратьте на него свое время. Вместо этого найдите какое-то большее улучшение. Например, индексы и сводные таблицы часто предоставляют 10x (не только 10%).