У меня есть несколько больших таблиц для бизнес-данных с наименьшим числом, имеющим 38 миллионов строк (данные 24G, размер индекса 26G). У меня есть установки индексов, чтобы ускорить поиск и буферный пул, установленный на 80% от общей ОЗУ (116G). Даже после этих настроек со временем мы начали наблюдать за проблемами производительности. У меня есть ограничения с размером диска (1T), и в настоящее время оштрафование не является вариантом. Рост данных увеличился до 0,5 М строк в день. Это приводит к частой оптимизации и мастер-переключателям. Табличные схемы и индексы уже оптимизированы. Следовательно, я начал рассматривать разделение таблицы для повышения производительности. Моим основным примером использования разделов является удаление данных ежемесячно, отбрасывая разделы, чтобы оптимизация не требовалась, а задержки чтения и записи улучшались. Ниже приведена структура для одной из больших таблиц (имена столбцов были изменены по юридическим причинам - предположим, что столбцы, в которых индексы определены, используются для поиска):
CREATE TABLE 'table_name' (
'id' int(11) NOT NULL AUTO_INCREMENT,
'data_1' int(11) NOT NULL,
'data_2' varchar(40) COLLATE utf8_unicode_ci NOT NULL,
'data_3' varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
'data_4' varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
'created_at' datetime DEFAULT NULL,
'updated_at' datetime DEFAULT NULL,
PRIMARY KEY ('id'),
KEY 'index_data1' ('data_1'),
KEY 'index_data2' ('data_2')
) ENGINE=InnoDB AUTO_INCREMENT=100572 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Я планирую разбить столбец created_at. Однако проблема заключается в том, что столбец разделения должен быть частью всех уникальных ключей. Я могу добавить столбец created_at в первичный ключ, но это приведет к увеличению размера индекса, который, в свою очередь, будет иметь свои собственные побочные эффекты. Есть ли какое-нибудь решение?
Помимо решения этой проблемы есть еще несколько вопросов, ответы на которые не могут быть найдены ни в каких документах или статьях. 1. Почему mysql требует, чтобы разделительный столбец был частью уникального ключа? 2. Запросы от ORM не имеют существующего предложения created_at, что означает, что обрезка невозможна при чтении, которое было в порядке, если предоставленные вставки всегда обрезаны. Однако не похоже, что это так. Почему mysql открывает все разделы для вставок?
Версия Mysql - 5.6.33-79.0-журнал Percona Server (GPL), версия 79.0, версия 2084bdb
PRIMARY KEY(id, created_at)
займет лишь немного PRIMARY KEY(id)
пространства, чем PRIMARY KEY(id)
. Я оцениваю его на уровне менее 1% для ваших данных. Я не могу сказать об индексном пространстве - можете ли вы показать нам непервичный индекс (ы)?
Объяснение: Листовые узлы данных (которые BTTI организованы ПК) не изменятся по размеру. Не-листовые узлы будут created_at
в каждой строке. Как правило, в InnoDB, не-листовые узлы занимают около 1% пространства для BTree.
Для INDEX
BTrees, узлы листа нуждаются в дополнительных 4 байтах/строке для created_at
если created_at
уже находится в индексе.
Скажем, у вас в настоящее время есть INDEX(foo)
где foo
- INT
а id
также INT
. Это всего 8 байт (плюс накладные расходы). Добавление created_at
(4-байтовый TIMESTAMP
) расширяет каждую строку листа до 12 + служебных данных. Таким образом, этот индекс может удвоиться.
Догадка: ваш 24G + 26G может вырасти до 25G + 33G.
Похоже, у вас есть несколько индексов. Вы понимаете, что INDEX(a)
не полезен, если у вас также есть INDEX(a,b)
? И что INDEX(x,y)
INDEX(x), INDEX(y)
в некоторых ситуациях намного лучше, чем INDEX(x), INDEX(y)
? Позвольте обсудить ваши индексы.
Основное преимущество PARTITIONing
- ваш прецедент - DROP PARTITION
намного быстрее DELETE
. Мой блог на таких.
Не увлекайтесь разделением. Вы надеетесь, что "латентности чтения/записи улучшены"; такое вряд ли произойдет. Если вы хотите получить дополнительные разъяснения, предоставьте SELECT
где, по вашему мнению, это может произойти.
Сколько "месяцев" вы разделите? Я рекомендую не более 50. PARTITIONing
имеет некоторые недостатки, когда есть много разделов.
Из-за необходимости ключа ключа в ключах UNIQUE
ограничение уникальности почти полностью бесполезно. Наличие в конце идентификатора AUTO_INCREMENT
не является проблемой.
Подумайте, может ли быть что-то другое, кроме id
.
Вопрос 1: При INSERTing
строки все ключи UNIQUE
сразу проверяются на "dup key". Без ключа раздела, являющегося частью уникального ключа, это будет означать исследование каждого раздела. Это слишком дорого обойтись; так что это не было сделано. (В будущем может быть реализован ключ UNIQUE
"глобальный для таблицы". Версия 8.0 имеет некоторые перехватчики для таких.)
Вопрос 2a: Да, если SELECT's
- SELECT's
WHERE
не адекватно указать ключ раздела, все разделы будут открыты и смотрели. Это еще одна причина для минимизации количества разделов. Hmmm... Если вы делаете SELECT
в 31-м месяце и выполняете тот же SELECT
на следующий день, вы можете получить меньше строк (даже без каких-либо удалений, просто DROP PARTITION
); это кажется "неправильным".
Вопрос 2b: "Почему mysql открывает все разделы для вставок?" - Почему вы думаете, что это так? Существует нечетный случай, когда "первый" раздел "излишне" открыт - ключ раздела DATETIME
.