3

CSV ファイルから 1 日 3 回、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 に変更すると、平均して 1 秒あたりの ubdate の数が 7 から 27 に増加しました。これは、そもそも大幅な増加です。

case 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 に追加のプロセッサを追加しようとしたところ、1 秒あたり約 4 つのクエリが高速化されました。

4

4 に答える 4

6

MySQL のCSV ストレージ エンジンを使用して、CSV ファイルに直接アクセスするテーブルを作成できます。インポートする必要はありません。

次に、複数テーブルの UPDATE 構文productsを使用して、列を使用して CSV テーブルをテーブルに直接結合できproduct_codeます。products次に、CSV テーブルから読み取った列に基づいて の列を更新できます。

于 2013-06-07T20:39:21.400 に答える
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

これらの 2 つのことで、速度が向上するはずです。

于 2013-06-07T20:45:35.023 に答える