2014-10-29 58 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