php - MySQL 查询(28K 行)使服务器过载

标签 php mysql apache opencart

我们正在运行 OpenCart 商店,现在我们必须导出 6 个月的订单数据(大约 17K 个订单)。

Opencart 有一个内置解决方案,当您选择所需的订单并导出时,它可以正常处理少于 500 个订单。

我决定根据其用于原始导出的查询制作一个独立脚本。

我不会发布导出部分,因为当我为 mysql_fetch_assoc 运行以下查询和后续循环时,我的专用服务器和存储会卡住。

   $query  = "SELECT o.*, op.name, op.model,op.order_product_id, op.product_id, op.quantity, op.price, op.total AS ptotal, op.tax,
  (SELECT ot.value FROM order_total ot WHERE ot.order_id = o.order_id AND ot.code = 'sub_total') AS sub_total,
  (SELECT ot.value FROM order_total ot WHERE ot.order_id = o.order_id AND ot.code = 'credit') AS store_credit,
  (SELECT `name` FROM order_history oh INNER JOIN `order_status` os on oh.order_status_id=os.order_status_id WHERE oh.order_id = o.order_id and os.language_id='2'
   ORDER BY order_history_id DESC LIMIT 1) as order_status 
   FROM `order` o inner join `order_product` op on o.order_id=op.order_id  WHERE o.date_added BETWEEN '2014-01-01 00:00:00' AND '2014-06-30 03:59:59'";

             $sql = mysql_query($query);

             do {

             echo $o['model']."<br/>"; // here we will have a part using PEAR Excel basically

             } while ($o=mysql_fetch_assoc($sql));
             $endtime = microtime();

             echo $endtime-$starttime;

索引已设置。在 oh.order_id 上设置了附加索引。没有运气。对 1 个特定订单 ID 的相同请求运行时间为 0.003 毫秒。

我的进程列表显示上面显示的查询的“发送数据”和其他查询的“等待表级锁定”。

您能帮忙吗?

最佳答案

我认为你可以稍微优化你的 SQL 以防止锁定。以下内容可能会有所帮助,但请注意,我没有您的架构或数据来测试它,因此您可能需要进行调整。

SELECT o.*, op.name, op.model,op.order_product_id, op.product_id,
       op.quantity, op.price, op.total AS ptotal, op.tax,
       ot.sub_total, ot.store_credit, os.os_name 
FROM `order` o inner join `order_product` op on o.order_id=op.order_id
INNER JOIN (SELECT t.order_id,
    MAX(case when t.code = 'sub_total' t.value else 0 end case) as sub_total, 
    MAX(case when t.code = 'credit' t.value else 0 end case) as store_credit 
  FROM order_total t GROUP BY t.order_id) ot ON ot.order_id = o.order_id
INNER JOIN (SELECT * FROM (SELECT oh.order_id, `name` AS os_name
  FROM order_history oh 
     INNER JOIN `order_status` s on oh.order_status_id=s.order_status_id
     WHERE s.language_id='2' ORDER BY order_history_id DESC) t1 
   GROUP BY t1.order_id) as os ON os.order_id = o.order_id
WHERE o.date_added BETWEEN '2014-01-01 00:00:00' AND '2014-06-30 03:59:59'

我也可能会执行create temp table temp_order_history from select ...,然后select * from temp_order_history此外,您可能需要执行外连接而不是内连接如果这些子选择中的任何一个缺少数据,则加入。在这些情况下,您只会得到这些列的 NULL。

关于php - MySQL 查询(28K 行)使服务器过载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27043984/

相关文章:

php - 在Laravel中whereraw与DB::raw

javascript - PHP 无法使用 Jquery 表单中的提交按钮

mysql - 创建引用不重复的用户的联系人数据库

apache - MAMP Pro 中的 HTTP2 支持

java - Apache http客户端

PHP - 在新窗口中打开链接?

php - 有没有办法只为给定的 PHPUnit 测试加载特定的装置?

php - MySQL WHERE IN () + AND , PDO 只返回一行

php - Laravel 5.5 枢轴连接以获取主 MySQL 结果的枢轴值

php - AddHandler 不适用于 .php 文件 - Apache 2.4