3

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

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

4 回答 4

6

您可以使用 MySQL 的CSV 存储引擎创建一个直接访问您的 CSV 文件的表。不需要导入它。

然后,您可以使用多表 UPDATE 语法将 CSV 表直接连接到products使用product_code列的表中。然后,您可以products根据从 CSV 表中读取的列更新列。

于 2013-06-07T20:39:21.400 回答
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
于 2013-06-07T20:43:40.367 回答
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

这两件事应该加快速度。

于 2013-06-07T20:45:35.023 回答
0

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

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

于 2013-06-07T20:50:26.693 回答