Mysql эффект разделения на индекс

0

У меня есть несколько больших таблиц для бизнес-данных с наименьшим числом, имеющим 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

Теги:
database
database-performance
partitioning

1 ответ

1

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.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню