2014-10-29 148 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); 
    } 

起初它運行速度非常快,當我做「SHOW PROCESSLIST」我看到,查詢取1秒。

但後來變得非常慢,查詢需要1個小時。

我在QA srv上運行,未被其他人使用。

我有很多的可用磁盤空間(3.5G)

有80308的產品在DB。

和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. – 2014-10-30 05:57:43

+0

確實有幫助,仍然掛起 - | 74 | root | localhost | prestashop2 |查詢| 144 |發送數據|插入到deleted_products中從p產品中選擇p。*,其中p.should_delete ='1'limit 1 | – 2014-10-30 06:44:33

回答

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

請注意,我能夠改進你提到的這部分查詢(請參閱我的問題的結尾)。問題是插入 – 2014-10-30 04:59:59

+0

@ user1406269這可能是由於你的where p.should_delete。 ='1'限制500'條件,因爲p.should_delete列未被索引,當值增加時需要更長的時間。因此,我的建議是添加一個[此列的索引](http://dev.mysql.com/doc/refman/5.0/en/create-index.html),如下所示。 'ALTER TABLE delete_product ADD INDEX product_ind USING BTREE(should_delete ASC);' – Payam 2014-10-30 08:27:26