InnoDB вставляет очень медленно и медленно

Я недавно переключил свои таблицы проекта на InnoDB (подумав, что отношения были бы неплохим вариантом). Я использую PHP-скрипт для одновременного индексирования около 500 товаров.

Таблица, в которой хранятся ассоциации слова / идентификаторы:

    CREATE TABLE `windex` (
 `word` varchar(64) NOT NULL,
 `wid` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `count` int(11) unsigned NOT NULL DEFAULT '1',
 PRIMARY KEY (`wid`),
 UNIQUE KEY `word` (`word`)
) ENGINE=InnoDB AUTO_INCREMENT=324551 DEFAULT CHARSET=latin1

В другой таблице хранятся ассоциации идентификаторов продуктов и идентификаторов слов:

CREATE TABLE `indx_0` (
 `wid` int(7) unsigned NOT NULL,
 `pid` int(7) unsigned NOT NULL,
 UNIQUE KEY `wid` (`wid`,`pid`),
 KEY `pid` (`pid`),
 CONSTRAINT `indx_0_ibfk_1` FOREIGN KEY (`wid`) REFERENCES `windex` (`wid`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `indx_0_ibfk_2` FOREIGN KEY (`pid`) REFERENCES `product` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Скрипт был протестирован с использованием MyISAM, и он относительно быстро индексирует продукты (намного, намного быстрее, чем InnoDB). Первый запуск в InnoDB был смехотворно медленным, но после объединения большего количества значений я в конечном итоге значительно ускорил его (но недостаточно).

Я предполагаю, что innodb будет намного быстрее для этого типа вещей из-за блокировок на уровне строк, но это не так.

Я создаю запрос, который выглядит примерно так:

SELECT
title,keywords,upc,...
FROM product
WHERE indexed = 0
LIMIT 500

Я создаю цикл и заполняю массив всеми словами, которые нужно добавить в windex, и всеми парами «идентификатор слова / идентификатор продукта», которые необходимо добавить в indx_0 .

Поскольку innodb продолжает увеличивать мои значения автоинкремента всякий раз, когда я выполняю команду «REPLACE INTO» или «INSERT IGNORE INTO», которая не выполняется из-за повторяющихся значений, мне нужно убедиться, что добавляемые мной значения еще не существуют. Для этого я сначала выбираю все существующие значения, используя такой запрос:

SELECT wid,word
FROM windex
WHERE
word = "someword1" or word = "someword2" or word = "someword3" ... ...

Затем я отфильтровываю свой массив по существующим результатам, поэтому все новые слова, которые я добавляю, являются на 100% новыми.

Это занимает около 20% от общего времени выполнения. Остальные 80% идут на добавление парных значений в indx_0, для которого существует намного больше значений.

Вот пример того, что я получаю.

0,4806 секунды для выбора продуктов. (Всего 0,4807 с).
0,0319 секунды, чтобы собрать 500 предметов. (Всего 0,5126 сек).
5,2396 секунд, чтобы выбрать значения Windex для сравнения. (Всего 5,7836 с).
1.8986 секунд до обновления счетчика. (Всего 7,6822 секунды).
0,0641 секунды, чтобы добавить 832 записи Windex. (Всего 7,7464 секунды).
17,2725 секунды, чтобы добавить индекс из 3435 пар pid / wid. (Всего 25,7752 секунды).
Операция заняла 26,07 секунды, чтобы проиндексировать 500 товаров.

Все 3435 пар выполняются в одном запросе, например:

INSERT INTO indx_0(pid,wid)
VALUES (1,4),(3,9),(9,2)... ... ...

Почему InnoDB намного медленнее MyISAM в моем случае?

10
задан Pacerier 9 April 2015 в 13:32
поделиться