我们正在运行 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/