@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`;
  • Вопрос задан
  • 78 просмотров
Решения вопроса 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 происходит в транзакции и не чего не блокирует или Вы имеете ввиду что по времени выполнения обновления увеличивает продолжительность отработки запроса?
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы