2014-10-29 3 views
1

У меня есть сайт электронной коммерции со многими старыми продуктами, которые никогда не используются.MySql зависает при обновлении и вставке

Я написал код, чтобы найти эти продукты и переместить их на другой стол.

Код находит продукты, которые необходимо удалить, и пометьте их столбцом should_delete = 1;

здесь код, копируете продукт (количество = количество продукта для удаления):

while ($count>0) 
    { 
     if ($db->Execute("insert into delete_product select p.* product p where p.should_delete ='1' limit 500")){ 
      $db->Execute("update product p set p.should_delete='2' where p.id_product in (SELECT `id_product` FROM deleted_products)"); 

     } 

     $count-= 500; 
     sleep(1); 
    } 

Сначала он работает очень быстро, когда я «шоу PROCESSLIST» Я вижу, что запрос взять 1 сек.

Но тогда он становится очень медленным, и запросы занимают 1 час.

Я работаю на QA srv, который не используется другими пользователями.

У меня есть много свободного места на диске (3.5G)

там 80308 продуктов в БД.

и 29511 это знак для удаления.

ДБ в InnoDB

это работает в течение нескольких часов в настоящее время, но только в 6500, где копируются.

«Показывать PROCESSLIST» шоу «Отправка данных» состояние

Что мне не хватает? почему эти простые запросы настолько медленны?

я был в состоянии улучшить второй запрос -

update product p 
join deleted_products dp on p.id_product = dp.id_product 
    set p.should_delete='2' 
where p.should_delete='1' 

Но вставка до сих пор висит.


вот другой вариант той же кода, который также висит -

while ($count>0) 
    { 
     $fname = microtime(true); 
     $db->Execute("SELECT * FROM product p where p.should_delete='1' LIMIT 500 INTO OUTFILE '/tmp/".$fname.".txt'"); 
     if ($db->Execute("LOAD DATA INFILE '/tmp/".$fname.".txt' INTO TABLE deleted_products" 
      )){ 
      $db->Execute("update product p join deleted_products dp on p.id_product = dp.id_product set p.should_delete='2' where p.$should_delete='1'"); 
     } 

     $count-= 500; 
     sleep(1); 
    } 

Эта версия висит -

58 | root | localhost | prestashop2 | Query | 29192 | NULL | LOAD DATA INFILE '/tmp/1414615714.6019.txt' INTO TABLE deleted_products 

это выглядит как deleted_products как-то замки, но это новое таблицу, которую я создал, и где-то еще нет в коде, это ссылка, и никто другой не использует этот srv.

+0

кажется, что я нашел решение, я меняю шаги от 500 до 1. –

+0

помог, все еще висит - | 74 | корень | localhost | prestashop2 | Запрос | 144 | Отправка данных | insert в deleted_products выберите p. * из продукта p, где p.should_delete = '1' limit 1 | –

ответ

0

Это вопрос дискового пространства. Я искал неправильный диск в df -h, я добавляю больше места, и он был решен.

1

Таблица deleted_products увеличивается каждый раз, когда этот цикл проходит. Поэтому, когда проходит время в этой части вашего запроса увеличивается:

where p.id_product in (SELECT `id_product` FROM deleted_products)" 

так представляют себе начинается с 500, то он попадет в 1000,1500, ... пока это очень медленно. Поэтому мое предложение состоит в том, чтобы добавить к нему условие, следующее ниже.

&AnAwesomeNewVariable=501; 
while ($count>0) 
{ 
    if ($db->Execute("insert into delete_product select p.* 
     product p where p.should_delete . ='1' limit 500")) 
{ 
$db->Execute("update product p set 
p.should_delete='2' where p.id_product in 
(SELECT `id_product` FROM deleted_products where 
id_product<&AnAwesomeNewVariable AND id_product >&AnAwesomeNewVariable-500)"); 

     } 

    $count-= 500; 
    &AnAwesomeNewVariable+=500; 
    sleep(1); 
} 
+0

Обратите внимание, что я смог улучшить эту часть запрошенного вами запроса (см. Конец моего вопроса). проблема заключается в вставке –

+0

@ user1406269, вероятно, из-за вашего 'where p.should_delete. = '1' limit 500', так как столбец p.should_delete не индексируется, это займет больше времени, когда значение увеличивается. Поэтому мое предложение состоит в том, чтобы добавить [индекс для этого столбца] (http://dev.mysql.com/doc/refman/5.0/en/create-index.html) следующим образом. 'ALTER TABLE delete_product ADD INDEX product_ind ИСПОЛЬЗОВАНИЕ BTREE (should_delete ASC);' – Payam

Смежные вопросы