当使用表product
中的数据执行WHILE LOOP并更新同一数据库中的另一个表stock_figures
时,下面的代码运行得非常慢。
代码遍历product
中的每一行,从product_id
和wholesale_price
中获取值,然后在product
表上执行一些计算,然后用这些值更新stock_figures
表。
如果有任何能提高我的查询性能的建议,我将不胜感激。
<?
// Retrieve data from database
$loop = " SELECT product_id, wholesale_price FROM product";
$query= mysql_query($loop);
while($rows=mysql_fetch_assoc($query))
{
$row = mysql_fetch_row($query);
$id = $row[0];
$price = $row[1];
?>
查询WHILE循环
<?
$bawtry_stock = "
SELECT product_id,
( kids_uk_j_105 + kids_c_17 + kids_c_18 + kids_c_19 + ... etc )
AS SUM FROM product WHERE product_id = '$id'";
$result_bawtry = mysql_query($bawtry_stock) or die (mysql_error());
$line = mysql_fetch_row($result_bawtry);
$bawtry = $line[1];
$chain_stock = "
SELECT product_id,
(quantity_c_size_26_chain + quantity_c_size_28_chain + quantity_c_size_30_chain +
... etc )
AS SUM FROM product WHERE product_id = '$id'";
$result_chain = mysql_query($chain_stock) or die (mysql_error());
$line = mysql_fetch_row($result_chain);
$chain = $line[1];
/*
* Declare the total value of all pairs from Bawtry, Chain
*/
$totalpairs = $chain + $bawtry;
/*
* Insert values for stock to write to databse
* Total stock for Bawtry, Chain
* Total value of stock for Bawtry, Chain
*
*/
$bawtry_value = (float)($bawtry * $price);
$chain_value = (float)($chain * $price);
$total_value = (float)($price * ($bawtry + $chain));
$sql2="
UPDATE stock_figures SET
bawtry_stock='$bawtry',
chain_stock='$chain',
totalstock='$totalpairs',
bawtry_value='$bawtry_value',
chain_value='$chain_value',
totalvalue='$total_value'
WHERE id='$id'";
$result2=mysql_query($sql2) or die (mysql_error());
?>
// close while loop
<? } ?>
<<p> 更新代码/strong> $sql = "SELECT product_id, wholesale_price,
(kids_uk_j_105 + kids_c_17 + kids_c_18 + kids_c_19 + kids_c_20 + kids_c_21 +
... )
AS bawtry,
(quantity_c_size_26_chain + quantity_c_size_28_chain + quantity_c_size_30_chain +
... )
AS chain from product";
$result = mysql_query($sql) or die (mysql_error());
while ($line=mysql_fetch_assoc($result))
{
$id = $line['product_id'];
$price = $line['wholesale_price'];
$bawtry = $line['bawtry'];
$chain = $line['chain'];
/*
* Declare the total value of all pairs from Bawtry, Chain
*/
$totalpairs = $chain + $bawtry;
/*
* Insert values for stock to write to database
* Total stock for Bawtry, Chain
* Total value of stock for Bawtry, Chain
*
*/
$bawtry_value = (float)($bawtry * $price);
$chain_value = (float)($chain * $price);
$total_value = (float)($price * ($bawtry + $chain));
$sql2="
UPDATE stock_figures SET
bawtry_stock='$bawtry',
chain_stock='$chain',
totalstock='$totalpairs',
bawtry_value='$bawtry_value',
chain_value='$chain_value',
totalvalue='$total_value'
WHERE id='$id'";
$result2=mysql_query($sql2) or die (mysql_error());
然而,它仍然需要一个绝对的时间来完成。当我在末尾注释掉UPDATE语句时,它似乎运行得非常快。显然,这需要保留在代码中,所以我可能会将整个东西作为cronjob运行。
除非可以提出任何进一步的改进建议?
似乎你做了很多浪费的选择。
首先从表产品中选择一些数据,然后从同一表中再次选择每一行。两次。最后将其插入另一个表stock_figures.
你所做的唯一的操作就是把许多数字加在一起。
所有这些都可以在一个查询中完成。
select product_id,
whole_sale_price,
sum(kids_uk_j_105,
kids_c_17,
...) as bawtry,
sum(quantity_c_size_26_chain,
quantity_c_size_28_chain,
...) as chain
from products;
如果这仍然花费很多时间,你需要检查一些服务器设置和行数
你所做的每一个写都是一个事务,根据你的acid级别,提交可能会很慢。将innodb-flush-log-at-trx-commit设置为2会加快写速度。
您正在对products-table进行全表扫描。我想这是有意为之,但如果这个表很大,读取它将花费一些时间,并且将所有这些行写回stock_figures将花费更长的时间。
考虑另一种方法。对于产品的每次写入(插入、更新或删除),都有一个触发器更新stock_figures中相应的行。它不仅可以消除批处理作业,还可以使stock_figures在任何给定时间都是正确的。
第一件事是:
$row = mysql_fetch_row($query);
$id = $row[0];
$price = $row[1];
我不知道它是否适合你,但是你已经在你的while
条件下使用了$rows,所以可能你应该把它改成:
$id = $rows['product_id'];
$price = $row['wholesale_price'];
接下来的两个查询你可以合并info:
SELECT product_id,
( kids_uk_j_105 + kids_c_17 + kids_c_18 + kids_c_19 + ... etc )
AS `SUM` FROM product WHERE product_id = '$id'
UNION ALL
SELECT product_id,
(quantity_c_size_26_chain + quantity_c_size_28_chain + quantity_c_size_30_chain +
... etc )
AS `SUM` FROM product WHERE product_id = '$id'
甚至:
SELECT product_id,
( kids_uk_j_105 + kids_c_17 + kids_c_18 + kids_c_19 + ... etc )
AS `SUM1`,
(quantity_c_size_26_chain + quantity_c_size_28_chain + quantity_c_size_30_chain +
... etc )
AS `SUM2`
FROM product WHERE product_id = '$id'
因为这两个查询是在同一个表上运行的。
但事实上,你可以使用一个查询来获得关于你的产品的所有信息,正如Andreas Wederbrand在他的回答中指出的。
但是还有更多的问题:
您使用旧的
mysql_
函数而不是mysqli_
或PDO
,您的代码容易受到SQL注入对于每个产品,你运行2个额外的查询(选择与联合所有,如果你走我的方式和更新)。
- 我不知道你有多少产品,但如果你有1000种或10000种产品,你不能指望它会很快。在这种情况下,您应该以某种方式在cron中运行脚本或刷新页面,并为少量产品(例如一次为10或100个产品)执行任务
- 您还应该考虑您的数据库结构是否是最好的。通常使用许多列作为你这里
kids_uk_j_105
,kids_c_17
,kids_c_18
不是最好的选择。
我希望你至少在product_id
列设置了键primary_id
在执行许多SQL命令时,解析它们需要一些时间。您可以通过使用http://php.net/manual/en/mysqli.quickstart.prepared-statements.php来减少这种开销你得到多少,取决于情况。
预处理语句从安全性考虑也是很好的。
这个答案不会使这里的其他答案无效。通过减少查询的数量,分析它们的工作,如果可能的话合并它们来提高效率。