@Kerm

Вопрос по MySQL, правильно ли в engine=memory делать insert?

Для оптимизации импорта товаров в интернет магазин, хочу сначала обновленные данные со склада заносить во временную таблицу в памяти, а после считывать из нее обновленные данные и записывать их в таблицу интернет магазина. Везде, просто везде пишут про то что создавать временные таблицы, в том числе в памяти нужно сразу с селектом из других таблиц. Я хочу создать временную пустую таблицу в памяти, сделать в нее insert, а после считать из этой таблицы инфу для дальнейшей работы с ней. По моему представлению данная операция должна оптимизировать/ускорить процесс импорта на сайт. Напрямую заливать инфу в те таблицы откуда происходит селект на сайт, я не очень хочу делать.

Вообщем главный вопрос вообще я делаю правильно или не правильно в плане так обычно делают или это вообще анархия и лучше сделать по другому?

У меня уже есть таблица с данными о товарах, откуда берется инфа на сайт:

CREATE TABLE `test` (
  `prod` int(10) unsigned NOT NULL,
  `type` int(10) unsigned NOT NULL,
  `pict` int(10) unsigned NOT NULL,
  `updated` int(1) unsigned DEFAULT '1',
  PRIMARY KEY (`prod`,`type`,`pict`)
) ENGINE=InnoDB;


Далее я обновляю эту таблицу со склада:

DROP TEMPORARY TABLE IF EXISTS `test123`;

CREATE TEMPORARY TABLE `test123` (
		`prod` int(10) unsigned NOT NULL,
        `type` int(10) unsigned NOT NULL,
        `pict` int(10) unsigned NOT NULL,
        PRIMARY KEY (`prod`,`type`,`pict`)
        ) ENGINE = MEMORY;

insert into `test123` values (1,1,1),(2,2,2);


Далее я запускаю хранимую процедуру с транзакцией:

DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `sync_fl2`()
BEGIN

DECLARE exit handler for sqlexception
  BEGIN
    -- ERROR
  ROLLBACK;
END;

DECLARE exit handler for sqlwarning
 BEGIN
    -- WARNING
 ROLLBACK;
END;

START TRANSACTION;

  UPDATE `test` SET `updated` = 0;

  INSERT INTO `test` (`prod`,`type`,`pict`) 
    SELECT `prod`,`type`,`pict`
    FROM `test123`
    ON DUPLICATE KEY UPDATE `updated` = 1;

DELETE FROM `test` WHERE `updated` = 0;

COMMIT;
END$$
DELIMITER ;


DROP TEMPORARY TABLE IF EXISTS `test123`;
  • Вопрос задан
  • 84 просмотра
Решения вопроса 1
@BorisKorobkov Куратор тега MySQL
Web developer
Такой вариант возможен.

Но получается большой overhead:
1. поддержание составного ключа. Хотя, возможно, без него не обойтись.
2. лишнее поле updated
3. обновление всех записей при UPDATE `test` SET `updated` = 0

Попробуйте:
1. удалить поле updated
2. multi-delete для удаления данных из test, которых нет test123
3. multi-update test из test123, если еще еще какие-то поля, кроме указанных
4. multi-delete из test123 записей из предыдущего пункта
5. insert-select новых записей
В зависимости от ваших реальных полей и количества записей мой вариант может быть как быстрее, так и медленнее. Проверьте сами

P.S. 'ENGINE = MEMORY' для временных таблиц указывать не обязательно
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@Kerm Автор вопроса
Так 3. обновление всех записей при UPDATE `test` SET `updated` = 0 происходит в транзакции и не чего не блокирует или Вы имеете ввиду что по времени выполнения обновления увеличивает продолжительность отработки запроса?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы