Массовый импорт данных в таблицу MySQL без удаления индекса - PullRequest
0 голосов
/ 28 февраля 2019

У нас есть одна таблица размером 10 ТБ, 5 миллиардов строк.

create table dummy_table (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  type INT, -- ENUM type, only few fixed values
  create_date DATE,
  user VARCHAR(10),
  A VARCHAR(10),
  B VARCHAR(10),
  C VARCHAR(10),
  D VARCHAR(10)
)

Данные являются неизменяемыми (операция обновления не требуется. Только массовая вставка (т. Е. Ежедневная загрузка данных) и массовое удаление (т. Е. Ежемесячная очистка данных)).

Наше основное использованиерегистр для поиска по пользователю, а затем введите, а затем creation_date.Для этого я анализирую две стратегии

  1. STRATEGY1 : с помощью составного индекса:

create index user_type_creation_date_idx on dummy_table(user, type, create_date)

STRATEGY2 : через раздел и индекс

alter table dummy_table PARTITION BY LIST(type) SUBPARTITION BY HASH(YEAR(create_date) + MONTH(create_date)) ( PARTITION pA VALUES IN (0) ( SUBPARTITION s0, SUBPARTITION s1, .....) create index user_idx on dummy_table(user)

Операция SELECT дает практически одинаковое время выполнения.Проблема, с которой я сталкиваюсь, находится в массовой вставке.Мы пытаемся выкачать 30 миллионов строк (4,2 ГБ) из файла s3 в нем.

Без индекса и раздела загрузка такого объема данных занимает около 360 секунд.Но с STRATEGY2 время загрузки данных увеличено до 850 секунд, а с STRATEGY1 оно все еще работает с прошлых 15000 секунд и продолжает работать.

Удаление индекса не входит в сферу применения, так как его создание занимает более 7 часов, и мы планируем создать еще четыре составных индекса

- index on user, A
- index on user, B
- index on user, C
- index on user, D

Вот мои вопросы:

  • Во многих постах SO я читал НЕ для создания раздела, но, похоже, концепция разделов работает хорошо для массовой вставки.Что-то не так, что я делаю со STRATEGY1?
  • В любом случае можно ли увеличить скорость массовой вставки, такой как свойство section, sub-partition, mysql / innodb, поскольку у нас есть преимущество в виде одной (без какого-либо соединения) таблицы, котораятоже не требуется ОБНОВЛЕНИЕ ?
  • Есть ли способ увеличить скорость массовой загрузки, загружая несколько файлов параллельно? LOAD DATA FROM S3 блокирует другие подобные команды.Можем ли мы запустить их параллельно как-нибудь?

Версия: MySQL: 5.6

1 Ответ

0 голосов
/ 12 марта 2019

План A: Включите индекс, не разбивайте и предварительно сортируйте входящие данные по user + type + create_date.Это будет самый быстрый.Но для предварительной сортировки файла CSV требуется место.

План Б: Нет индекса, нет разделения, просто загрузите данные, но затем ADD INDEX.Для сортировки требуется огромное количество дискового пространства.Этот план может быть близок к плану A.

План C: если вам не нужны id и (user + type + create_date) уникален, то удалите id и выполните план А. Теперь это лучший подход.

Проблемы:

  • Секционирование не дает преимущества в производительности для вашей ситуации.
  • Вставка строкпо порядку или построению индекса путем сортировки - либо намного быстрее, чем случайным образом вставлять строки.
  • Больше индексов: (пользователь + A / B / C / D) - это также требует наличия user в качестве первый пункт в ПК.Сколько строк в user?(Похоже на миллионы?)
  • Вы упомянули ежемесячное удаление.Это действительно нужно PARTITION BY RANGE(TO_DAYS(...)) вместе с ежемесячными разделами.Это потому, что DROP PARTITION намного быстрее, чем DELETE.См. это для более подробной информации.Итак, теперь я рекомендую A или C, а также месячные разделы.
  • Если у вас должно быть id, то для общего SELECT (и из-за огромного размера данных),

do

PRIMARY KEY(user, type, create_date, id), -- clustered, unique, etc
INDEX(id)   -- sufficient to keep AUTO_INCREMENT happy

Математика озадачивает меня: строки 5B по 100 байт каждая будут занимать около 1 ТБ (после издержек InnoDB), но вы говорите 10 ТБ.

Я предположилInnoDB;если вы используете какой-то другой движок, мне может потребоваться изменить мой ответ.

Думая дальше «из коробки» ...

С InnoDB и параллельными нагрузками вы сможетесделайте следующее с "транспортабельными табличными пространствами".Но он не доступен для разделов до 5.7.4.

Это может включать в себя запуск нескольких отдельных загрузок, каждая загрузка в отдельную таблицу .Когда закончите, используйте «транспортабельные табличные пространства», чтобы переместить каждое в главную таблицу как раздел.

...