(я не согласен с некоторыми других ответов / комментариев. Я постараюсь ответить на все вопросы, а также ответить на все вопросы, с которыми я не согласен.)
MEDIUMINT
- 3 байта, экономя 1 байт на строку более INT
.
TINYINT
равен 1 байту, экономя 3 байта на строку более INT
.
В обоих случаях в каждом INDEX
, кроме PRIMARY KEY
.
, сохраняется 1 или 3 байта для каждого вхождения.
Если у вас в ОЗУ больше данных + индекса, чем места в ОЗУ, то целесообразно разумно уменьшить типы данных , но быть консервативным.
Используйте MEDIUMINT UNSIGNED
(и т. Д.), Если значение неотрицательно, например, для AUTO_INCREMENT
. Это дает вам предел 16M вместо 8M. (Да, да, это небольшое улучшение.)
Остерегайтесь "прожига" AUTO_INCREMENT
id - INSERT IGNORE
(и несколько других команд) выделят следующий auto_inc перед проверкой, будет ли он использоваться.
Даже если data + index превышает размер RAM (на самом деле innodb_buffer_pool_size
), он может не замедляться до скорости диска - это зависит от схем доступа к данным. Остерегайтесь UUID, они ужасно случайны. Использование UUID, когда вы не можете кэшировать весь индекс, смертельно. Буфер_пул - это кеш . (Я видел, что набор данных объемом 1 ТБ работал достаточно быстро, только с 32 ГБ ОЗУ и вращающимся диском.)
Использование ALTER TABLE
для изменения типа данных возможно (я не уверен) перестраивает таблицу, выполняя, таким образом, эквивалент OPTIMIZE TABLE
.
Если таблица была создана с помощью innodb_file_per_table = OFF
и вы поворачиваете ее ON
перед выполнением ALTER
, вы получите отдельный файл для таблицы, , но ibdata1
не будет уменьшаться (вместо этого у него будет намного больше свободного места).
Выравнивание 3-байтовых чисел - не проблема . Полномочия 2 здесь не актуальны. MySQL предполагает, что все столбцы имеют плохие границы и плохие размеры. Все числа преобразуются в общий формат (64-разрядные числа) для дальнейшей работы. Это преобразование составляет незначительную часть общего времени - выборка строки (даже если она кэширована) является самой дорогой частью.
При ограничении ввода / вывода сжатие типов данных приводит к увеличению числа строк в блоке, что приводит к меньшему количеству обращений к диску (за исключением случая UUID). При ограничении ввода / вывода попадание на диск приводит к огромным потерям производительности.
"NULLS не занимать пробел" - https://dev.mysql.com/doc/internals/en/innodb-field-contents.html. Итак, опять же, меньше ввода / вывода. Но будьте осторожны, если это приведет к дополнительной проверке NULL
в SELECT
, это может привести к сканированию таблицы вместо использования индекса. Удар по 10М рядам намного хуже, чем по нескольким.
Что касается того, сколько клиентов вы можете уместить в 32 ГБ - может быть, 6 или больше. Помните, буфер_пул является кешем; данные и индексы кэшируются по блокам. (Блок InnoDB составляет 16 КБ.)
Еще одна вещь ... Намного проще сократить типы данных до того, как поступит в производство. Итак, делай то, что можешь сейчас, смело.