МySQL оптимизировать множество replace запросов

Тема в разделе "Базы данных", создана пользователем setevoi, 28 апр 2015.

Модераторы: latteo
  1. setevoi

    setevoi Создатель

    Регистр.:
    10 апр 2013
    Сообщения:
    44
    Симпатии:
    14
    Есть обновление характеристик товара из эксель
    Как оптимизировать
    сейчас это более 3000 запросов и все растет в геометрической прогрессии :D

    Код:
    replace into goods_chars set content='Да',goods_id=110, char_id=434
    replace into goods_chars set content='Нет',goods_id=110, char_id=436
    replace into goods_chars set content='Иногда',goods_id=110, char_id=439
    replace into goods_chars set content='Есть',goods_id=110, char_id=474
    replace into goods_chars set content='Бывает',goods_id=110, char_id=484
    
    
    replace into goods_chars set content='нет',goods_id=120, char_id=586
    replace into goods_chars set content='Wi-fi',goods_id=120, char_id=589
    replace into goods_chars set content='есть',goods_id=120, char_id=590
    replace into goods_chars set content='Есть',goods_id=120, char_id=591
    replace into goods_chars set content='есть',goods_id=120, char_id=594
     
  2. ArtyGrand

    ArtyGrand Постоялец

    Регистр.:
    6 июн 2009
    Сообщения:
    80
    Симпатии:
    37
    Выглядит как хранилище ключ-значение.
    тут либо в транзакции обернуть, либо аяксом отправлять на правку каждое поле отдельно
     
    Black Hat нравится это.
  3. setevoi

    setevoi Создатель

    Регистр.:
    10 апр 2013
    Сообщения:
    44
    Симпатии:
    14
    в транзакции это как ?

    структура у таблиц под характеристики такая

    Код:
    CREATE TABLE IF NOT EXISTS `goods_chars` (
      `char_id` int(10) unsigned DEFAULT NULL,
      `goods_id` int(10) unsigned DEFAULT NULL,
      `content` varchar(255) DEFAULT NULL,
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      PRIMARY KEY (`id`),
      UNIQUE KEY `char_id` (`char_id`,`goods_id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=166084 ;
    
    
    CREATE TABLE IF NOT EXISTS `gt_chars` (
      `name` varchar(255) NOT NULL DEFAULT '',
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=473
     
    Последнее редактирование: 28 апр 2015
  4. dandandan

    dandandan

    Регистр.:
    7 авг 2008
    Сообщения:
    990
    Симпатии:
    267
    http://www.mysqltutorial.org/mysql-transaction.aspx
    http://www.weblibrary.biz/mysql/sintaksis-oper/uprav-tranzakciyami
    http://www.mysqltutorial.org/mysql-transaction.aspx


    Пример:
    PHP:
    mysql_query("START TRANSACTION");
    mysql_query("replace into goods_chars set content='нет',goods_id=120, char_id=586");
    mysql_query("replace into goods_chars set content='Wi-fi',goods_id=120, char_id=589");
    mysql_query("replace into goods_chars set content='есть',goods_id=120, char_id=590");

    // тут проверяем прошел ли replace нормально
    if ($a1 && $a2 && $a3) {
        
    mysql_query("COMMIT");
    } else {      
        
    mysql_query("ROLLBACK");
    }
     
    Black Hat нравится это.
  5. setevoi

    setevoi Создатель

    Регистр.:
    10 апр 2013
    Сообщения:
    44
    Симпатии:
    14
    с транзакциями понял, но не уверен что это правильное решение
    думаю в сторону
    UPDATE goods_chars A JOIN gt_chars B
    чтобы избавиться от ключа char_id

    Чтение мануала привело к такому решению )
    UPDATE нескольких строк за раз

    Код:
    insert into goods_chars (`char_id`,  `goods_id` ,  `content` ) 
    values(39,1,'Да'),(40,1,'Нет')
    on duplicate key update val =values(content);
     
    Последнее редактирование модератором: 29 апр 2015
    latteo нравится это.
  6. newminer

    newminer Создатель

    Регистр.:
    21 апр 2015
    Сообщения:
    13
    Симпатии:
    4
    Чтобы быстро работало, можно сделать так: Данные составить таким образом, чтобы они одним запросом (или несколькими, по 2000строк за раз) добавлялись в специально созданную таблицу
    Потом эти данные можно легко добавить с помощью хранимой процедуры, например.
     
  7. asc11

    asc11 Создатель

    Регистр.:
    1 авг 2007
    Сообщения:
    20
    Симпатии:
    4
    Если не ошибаюсь, с ON DUPLICATE KEY UPDATE крутится счетчик для primary key.

    ИМХО стоит его использовать там, где немного запросов
     
    Black Hat нравится это.
  8. Black Hat

    Black Hat Постоялец

    Регистр.:
    15 май 2015
    Сообщения:
    114
    Симпатии:
    76
    Транзакция, как пишет ArtyGrand, только вначале ALTER TABLE `...` ENGINE=InnoDB так как транзакции поддерживают далеко не все типы подсистем хранения. И только REPLACE INTO ..., так как ODKU забивает счетчик. По производительности - увеличить "key_buffer_size" до максимума, чтобы быстрее работать с индексами, уменьшить "max_heap_table_size" до 128MB, увеличить "tmp_table_size" - чем больше тем лучше
     
  9. r_219

    r_219 Постоялец

    Регистр.:
    20 мар 2015
    Сообщения:
    67
    Симпатии:
    11
  10. Funaki

    Funaki

    Регистр.:
    26 июн 2008
    Сообщения:
    151
    Симпатии:
    16
    а что если тебе использовать синтаксис для массовой вставки, вместо 3000 запросов используй 1 строку с кучей values
    Код:
    REPLACE INTO goods_chars (content,goods_id,char_id)
            VALUES ('Да',110,434),('Нет',110,436)...
    протести и как следующий вариант - можно попробовать исп. временную таблицу, а функцию replace сделать вручную через insert+delete но уже с таблицей