在PHP中执行多个MySQL查询的更有效方法

时间:2014-07-31 21:26:07

标签: php mysql sql performance

我有一个包含数千个订单的在线商店,我正在写一些查询,以确定每个供应商(品牌)在网站上赚了多少钱。我有以下查询,一个是所选年份的每个月:

$filterJan = "$filterYear-01";
$queryJan = "SELECT price, quantity FROM order_items WHERE productID='$productID' AND timestamp LIKE '%$filterJan%' LIMIT 10000";
$suppliersQueryFilter = mysql_query($queryJan, $connection) or die(mysql_error());

while($rowF = mysql_fetch_assoc($suppliersQueryFilter)) {
    $price = $rowF["price"]*$rowF["quantity"];
    $totalJan = $totalJan+$price;
}

**等等每个月**

加载需要很长时间(我们至少谈论超过60秒)并且我知道它在任何形状或形式上都没有效率。对于每个月,这些查询都会搜索数千条记录。有没有更有效的方式或写这个:

a)将代码量减少到1个查询 b)提高装载时间的效率

$ filterYear包含一年,如2009年。

所以这个查询的作用是它选择每个月为选定年份(分配给$ filterYear)赚了多少钱。所以它产生的结果是1月,2月,3月的表...每个月有多少钱,所以2345英镑,2101英镑等......

2 个答案:

答案 0 :(得分:2)

您应该将时间戳存储为实际的mysql日期时间值,这会产生类似

的内容
GROUP BY YEAR(timestamp), MONTH(timestamp)
WHERE timestamp BETWEEN $initialtime AND $finaltime
很可能。这样就可以将多个基本相同的重复查询减少到一个查询。

您可以为此使用派生值,但它的效率低于使用本机日期时间字段:

GROUP BY SUBSTR(timestamp, 0, 4), SUBSTR(timestamp, 6,2)

答案 1 :(得分:1)

为了获得最佳性能,您需要向数据库提交类似的查询:

SELECT DATE_FORMAT(i.timestamp,'%Y-%m') AS `month`
     , SUM(i.price*i.qty)               AS `total`
  FROM order_items i 
 WHERE i.productID  = 'foo'
   AND i.timestamp >= '2013-01-01'
   AND i.timestamp <  '2013-01-01' + INTERVAL 12 MONTH
 GROUP
    BY DATE_FORMAT(i.timestamp,'%Y-%m')

(这假设timestamp列是MySQL数据类型TIMESTAMPDATETIMEDATE

使用已弃用的mysql_接口,您希望使用mysql_real_escape_string函数来避免SQL注入漏洞。 (更好的选择是使用mysqli或PDO接口,并使用带有绑定占位符的预准备语句。)

我们希望时间戳上的谓词位于BARE列上,因此MySQL可以使用适用于范围扫描操作的合适索引,而不需要对表中的每一行进行完全扫描。

我们还想利用服务器的强大功能快速派生一个总数,然后只返回总数,而不是检索每个翻转行,并单独处理每个行(RBAR =通过痛苦排行)

GROUP BY子句和SUM()聚合函数是根据此结果量身定制的。

使用mysql_接口,查询看起来像这样:

$querytext = "
SELECT DATE_FORMAT(i.timestamp,'%Y-%m') AS `month`
     , SUM(i.price*i.qty)               AS `total`
  FROM order_items i 
 WHERE i.productID  = '" . mysql_real_escape_string($thisProductID) . "'
   AND i.timestamp >= '" . mysql_real_escape_string($filterYear) . "-01-01'
   AND i.timestamp <  '" . mysql_real_escape_string($filterYear) . "-01-01' + 
                      INTERVAL 12 MONTH
 GROUP BY DATE_FORMAT(i.timestamp,'%Y-%m')";

# for debugging
#echo $querytext;