MySQL LOAD DATA INFILE замедляется на 80% после нескольких гигов ввода с движком InnoDB

14

Я загружаю файл объемом 100 ГБ через LOAD DATA INFILE. У меня был хороший успех с MyISAM, несколько часов и все готово.

Я пытаюсь это сейчас, используя InnoDB. Загрузка начинается быстро со скоростью более 10 МБ / с (наблюдение за ростом файла таблицы file_per_tableвключено).

Но после примерно 5 ГБ данных он замедляется до диапазона 2-4 МБ / с, а когда я получаю более 20 ГБ, он снижается примерно до 2 МБ / с.

Размер буферных пулов InnoDB составляет 8G. И перед выполнением команды LOAD DATA INFILE я сделал следующее:

SET @@session.sql_log_bin=0;
SET autocommit=0;
SET unique_checks=0;
SET foreign_key_checks=0;
alter table item_load disable keys;
//Run LOAD DATA INFILE....

Я не вижу причины, по которой все начинается хорошо и со временем замедляется.

Кроме того, используя те же настройки, я выполнил ту же команду LOAD DATA INFILE с таблицей, используя InnoDB и MyISAM и набор тестовых данных 5 ГБ, MyISAM был в 20 раз быстрее:

InnoDB:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (21 min 25.38 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

MyISAM:

mysql> LOAD DATA CONCURRENT LOCAL INFILE '/tmp/item' REPLACE INTO TABLE item_load;
Query OK, 2630886 rows affected, 6 warnings (1 min 2.52 sec)
Records: 2630886  Deleted: 0  Skipped: 0  Warnings: 6

Что-нибудь еще, я должен рассмотреть попытку? Движок MyISAM способен намного лучше поддерживать скорость загрузки.


Дополнительные детали:

  • Я пытался загрузить файлы по отдельности, без разницы.

  • Кстати, у меня 150 файлов по 500 МБ каждый, в каждом файле ключи сортируются.

  • После получения 40 ГБ за ночь, 12 часов спустя, скорость загрузки снизилась до 0,5 МБ / с, что означает, что операция практически невозможна.

  • Других ответов на подобные вопросы на других форумах я не нашел, мне кажется, что InnoDB не поддерживает загрузку больших объемов данных в таблицы размером более нескольких ГБ.

Дэвид Паркс
источник

Ответы:

7

НАБЛЮДЕНИЕ № 1

Я заметил , что ты выключил autocommit. Это накапливает столько данных в ibdata1. Почему?

Существует семь (7) классов информации, которая хранится в ibdata1:

  • Страницы данных для таблиц InnoDB
  • Индексные страницы для таблиц InnoDB
  • Словарь данных
  • Двойной буфер записи
    • Сеть безопасности для предотвращения повреждения данных
    • Помогает обойти ОС для кеширования
  • Вставить буфер (упрощает изменение вторичных индексов)
  • Откат сегментов
  • Отменить Журналы
  • Нажмите здесь, чтобы увидеть графическое представление ibdata1

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

Рекомендация: оставить автокоммит включенным

НАБЛЮДЕНИЕ № 2

Я вижу, у вас есть это:

alter table item_load disable keys;

DISABLE KEYS не работает с InnoDB . Вот почему:

  • MyISAM: DISABLE KEYSпросто отключает обновление вторичного индекса для таблицы MyISAM. Массовая вставка INSERT в таблицу MyISAM с отключенными ключами приводит к быстрой загрузке таблицы вместе со сборкой PRIMARY KEY и всех уникальных индексов. При запуске ENABLE KEYSвсе вторичные индексы строятся линейно на таблице и добавляются к .MYD.
  • InnoDB: Как показано на внутренней картинке InnoDB, системное табличное пространство ibdata1имеет структуру, выделенную для вставок вторичного индекса. В настоящее время нет условий для обработки индексов, аналогичных MyISAM.

Чтобы проиллюстрировать это, обратите внимание на мою попытку запустить DISABLE KEYS для таблицы InnoDB в MySQL.

mysql> show create table webform\G
*************************** 1. row ***************************
       Table: webform
Create Table: CREATE TABLE `webform` (
  `nid` int(10) unsigned NOT NULL,
  `confirmation` text NOT NULL,
  `confirmation_format` tinyint(4) NOT NULL DEFAULT '0',
  `redirect_url` varchar(255) DEFAULT '<confirmation>',
  `status` tinyint(4) NOT NULL DEFAULT '1',
  `block` tinyint(4) NOT NULL DEFAULT '0',
  `teaser` tinyint(4) NOT NULL DEFAULT '0',
  `allow_draft` tinyint(4) NOT NULL DEFAULT '0',
  `submit_notice` tinyint(4) NOT NULL DEFAULT '1',
  `submit_text` varchar(255) DEFAULT NULL,
  `submit_limit` tinyint(4) NOT NULL DEFAULT '-1',
  `submit_interval` int(11) NOT NULL DEFAULT '-1',
  PRIMARY KEY (`nid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> alter table webform disable keys;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show warnings;
+-------+------+-------------------------------------------------------------+
| Level | Code | Message                                                     |
+-------+------+-------------------------------------------------------------+
| Note  | 1031 | Table storage engine for 'webform' doesn't have this option |
+-------+------+-------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select version();
+------------+
| version()  |
+------------+
| 5.5.27-log |
+------------+
1 row in set (0.00 sec)

mysql>

НАБЛЮДЕНИЕ № 3

Вы заметили, что MyISAM загружается в 20 раз быстрее, чем InnoDB. Хотели бы вы, чтобы это было больше в 24-25 раз быстрее? Затем выполните следующее:

ALTER TABLE item_load ROW_FORMAT=Fixed;

Это ускорит вставку в 20-25% без каких-либо других изменений DDL . Побочный эффект: размер таблицы MyISAM может увеличиться на 80-100%, возможно, увеличиться.

Вы также можете выполнить это для таблицы InnoDB, но ACID-совместимое поведение и MVCC InnoDB по-прежнему будут узким местом его производительности, особенно если поля VARCHAR значительно увеличиваются и записываются в них ibdata1.

RolandoMySQLDBA
источник
Первые 2 наблюдения были вещами, которые я попытался добавить, чтобы исправить проблему после того, как впервые заметил это, моей первой попыткой было, естественно, оставить innodb в покое (просто отключить ведение журнала bin). На 3-м наблюдении, мой размер данных сильно варьируется по длине, я полагаю, это будет проблемой? Я чувствую, что мне просто нужно сохранить этот стол myisam.
Дэвид Паркс
6

Окончательный ответ на этот вопрос состоял в том, чтобы не использовать InnoDB для массивной справочной таблицы. MyISAM кричит быстро, почти полная пропускная способность диска для всей нагрузки, InnoDB не работает. MyISAM прост, но в этом случае так же требования этой таблицы. Для простой справочной таблицы с объемными нагрузками через LOAD DATA INFILE MyISAM - это путь, который пока хорош.

Но обратите внимание, что если вы запустите таблицы MyISAM и InnoDB, то вам нужно будет рассмотреть вопрос о распределении памяти для двух механизмов кэширования, каждый механизм имеет свое уникальное кэширование, которое требует отдельного выделения памяти.

Дэвид Паркс
источник
5

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

Я лично использую http://www.percona.com/doc/percona-toolkit/2.1/pt-fifo-split.html для этого.

Что произойдет, если вы получите блокировку таблицы для таблицы во время импорта? Возможно, блокировка на уровне строк InnoDB замедляет его (MyISAM использует блокировку таблицы).

Вы также можете прочитать здесь для дальнейших идей: http://derwiki.tumblr.com/post/24490758395/loading-half-a-billion-rows-into-mysql

bnadland
источник
Мои файлы уже находятся в блоках по 500 МБ, я передавал их все по одному именованному каналу, чтобы облегчить загрузку, но сейчас попробую этот подход.
Дэвид Паркс
Не видя здесь никакой разницы, довольно быстро я вижу снижение скорости с 11 МБ / с расширения файла БД до 6 МБ (после примерно 2 ГБ) данных, и оно продолжает падать. Я загружаю все файлы в цикле for, отдельные вызовы mysql.
Дэвид Паркс
Первый файл загружается за 54 с, второй за 3 м 39 с, третий за 3 м 9, 4 м 7, 5 м 21 и т. Д. все файлы примерно одинакового размера.
Дэвид Паркс
2

Если ваш PK не AUTO_INCREMENT или данные в csv-файле не отсортированы на PK, это может повлиять на производительность загрузки данных. Так как таблица в MySQL является индексом, следовательно, все данные хранятся в отсортированном порядке, если значение PK не находится в AUTO_INCREMENT, то MySQL должен выполнить большое смещение данных, чтобы получить данные, сохраненные в отсортированном порядке. Это является причиной более медленной загрузки данных, когда размер таблицы начинает расти.

Я загружаю csv-файл 91 ГБ с PK на AUTO_INCREMENT, используя LOAD DATA INFILE, и я не вижу никакого падения в моей пропускной способности. Я получаю от 140К до 145К вставок в секунду. Использование Percona MySQL 5.6.38

KKYadav
источник