大规模的MySQL更新最佳方法?

时间:2013-06-07 20:29:09

标签: php mysql csv mysqli

我需要每天从CSV文件中更新MySQL数据库中的库存水平3次。

CSV中有超过27,000种产品需要更新,您可以想象它需要一段时间。

我目前有一个运行以下内容的PHP脚本:

select * from products where product_code = "xxxxxxx";
if num_rows > 0
    if new_stock_level = 0
        UPDATE products SET `stock` = 0, `price` = 9.99 where product_code = "xxxxxxx";
    else
        UPDATE products SET `stock` = 50, `price` = 9.99, `stock_date` = now() where product_code = "xxxxxxx";

如果你正在更新<这一切都很好。 50件但不是27,000件!

更新此比例的最佳方法是什么?

我一直在做一些研究,从我所看到的mysqli准备好的陈述似乎是我应该去的地方。

在尝试了下面提到的一些内容以及我在线阅读的内容之后,我已经获得了一批250次更新的结果。

从InnoDB更改为MyISAM平均每秒的ubdate数量从7增加到27,这是一个巨大的增长。

准备案件9-10秒

## Prepare the statment.
$stmt = $mysqli->prepare("UPDATE products SET stock = case ? when 0 then 0 else ? end, price = ?, stock_date = case ? when 0 then stock_date else now() end WHERE product_code = ?");
$stmt->bind_param('dddds', $stock, $stock, $price, $stock, $prod);
$stmt->execute();

非准备状态9-10秒

$sql = "UPDATE products SET stock = case " . $stock . " when 0 then 0 else " . $stock . " end, price = " . $price . ", stock_date = case " . $stock . " when 0 then stock_date else now() end WHERE product_code = \"" . $prod . "\";\n";
$mysqli->query($sql);

在50秒内对法规进行分组,并使用multi_query 9-10秒进行分析

$mysqli->multi_query($sql);

未准备好2个单独的查询,具体取决于我是否更新股票日期。 8-9秒

if($stock > 0)
{
    $sql = "UPDATE products SET stock = " . $stock . ", price = " . $price . ", stock_date = now() WHERE product_code = \"" . $prod . "\";\n";
}
else
{   
    $sql = "UPDATE products SET stock = " . $stock . ", price = " . $price . " WHERE product_code = \"" . $prod . "\";\n";
}
$mysqli->query($sql);

准备版本相同8-9秒

## Prepare statments
$stmt1 = $mysqli->prepare("UPDATE products SET stock = ?, price = ?, stock_date = now() WHERE product_code = ?;");
$stmt1->bind_param('dds',$stock, $price, $prod);
$stmt2 = $mysqli->prepare("UPDATE products SET stock = ?, price = ? WHERE product_code = ?;");
$stmt2->bind_param('dds', $stock, $price, $prod);

if($stock > 0)
{
    $stmt1->execute();
}
else
{   
    $stmt2->execute();
}

我还尝试在VPS上添加一个额外的处理器,它使得它的速度提高了4个查询速度。

4 个答案:

答案 0 :(得分:6)

您可以使用MySQL的CSV storage engine创建一个直接访问CSV文件的表。无需导入。

然后,您可以使用multi-table UPDATE syntax使用products列将CSV表格直接加入product_code表格。然后,您可以根据从CSV表中读取的列更新products列。

答案 1 :(得分:3)

我个人会将更新上传到临时表中,在product_code字段上创建一个唯一键,然后运行这样的更新......

UPDATE tmptable p, products pp 
SET pp.stock = p.stock,
    pp.price = p.price,
    pp.stock_date = if(p.stock == 0, now(), pp.stock_date)
WHERE pp.product_code = p.product_code

答案 2 :(得分:3)

有关这方面的一些事情......

1. you can do this with one sql statement 
UPDATE products 
SET stock = case new_stock_level when 0 then 0 else new_stock_level end, 
    price = 9.99,
    stock_date = case new_stock_level when 0 then stock_date else now() end
WHERE product_code = "xxxxxxx";

2. you might want to try wrapping the statements inside of a transaction:
e.g.
START TRANSACTION
UPDATE products ...;
UPDATE products ...;
... ;
COMMIT TRANSACTION

这两件事应该加快速度。

答案 3 :(得分:0)

好的,我知道这不是你问题的直接答案,但我想提出一个不同的方法。

尝试更新整个库存级别,尝试仅更新自上次更新以来发生更改的内容?您可以使用某种更改时间来跟踪它。 这在很大程度上取决于您的环境,但可能选择当前库存并将其与csv文件进行竞争(或者相反)实际上可以更快地更新每条记录。当然,这可能是完全浪费时间,但只有一种方法可以找到...