我有一个半复杂的JOIN
结构,根据订单从我的MySQL数据库中获取特定信息。首先让我给你SQL查询;
SELECT
#orders.*,
orders.id,
customers.lastname,
customers.priority,
shipments.status,
pmv_sl.productmodelvariant_id,
pmv_sl.nr AS pmv_nr,
COALESCE(SUM(orderlines.nr), 0) AS orderlines_nr_count,
COALESCE(SUM(shipment_lines.nr), 0) AS shipment_lines_nr_count
FROM orders
INNER JOIN customers ON customers.id = orders.customer_id
INNER JOIN platforms ON platforms.id = orders.platform_id
INNER JOIN stocklocations ON stocklocations.id = platforms.stocklocation_id
LEFT JOIN orderlines ON orderlines.order_id = orders.id
LEFT JOIN shipments ON shipments.order_id = orders.id
LEFT JOIN shipment_lines ON shipment_lines.shipment_id = shipments.id
# This JOIN, together with shipment_lines, makes the query suddenly very slow (probably because of all the SUM()'s)
LEFT JOIN productmodelvariants_stocklocations pmv_sl ON
pmv_sl.productmodelvariant_id = orderlines.productmodelvariant_id
AND pmv_sl.stocklocation_id = stocklocations.id
WHERE
orders.orderstatus_id = 2
AND orders.order_all_to_shipment = 0
GROUP BY
orders.id
问题
所以我计算了这个查询的4个速度(450个结果在所有情况下);
LEFT JOIN shipment_lines
且没有LEFT JOIN productmodelvariants_stocklocations
LEFT JOIN shipment_lines
LEFT JOIN productmodelvariants_stocklocations
2.
和3.
以下是结果速度;
表格中的行
orderlines
中的行:24528 shipment_lines
中的行:6345 productmodelvariants_stocklocations
中的行:1819 结论
正如您所看到的那样2.
和3.
(4.
)都参加了比赛; SQL开始破坏汗水。
我想知道是否有比我更多(我的)SQL知识的人知道一种改变查询上下文的方法来提升它。
我还注意到,在执行4.
并引用COALESCE(SUM()
时,我很容易获得0.8
到1.0
秒。
更新
EXPLAIN EXTENDED
答案 0 :(得分:2)
您正在创建交叉联接,因为未能在shipment.status
上指定join子句尝试重新组织您的查询:
SELECT A.*,
orders_id,
customers.lastname,
customers.priority,
# shipments.status,
pmv_sl.productmodelvariant_id,
pmv_sl.nr AS pmv_nr,
orderlines_nr_count,
shipment_lines_nr_count
FROM (
SELECT
#orders.*,
orders.id AS orders_id,
# shipments.status,
COALESCE(SUM(orderlines.nr), 0) AS orderlines_nr_count,
COALESCE(SUM(shipment_lines.nr), 0) AS shipment_lines_nr_count
FROM orders
LEFT JOIN orderlines ON orderlines.order_id = orders.id
LEFT JOIN shipments ON shipments.order_id = orders.id
LEFT JOIN shipment_lines ON shipment_lines.shipment_id = shipments.id
WHERE orders.orderstatus_id = 2
AND orders.order_all_to_shipment = 0
GROUP BY
orders.id,
orderlines.productmodelvariant_id,
stocklocations.id
) orders
INNER JOIN customers ON customers.id = orders.customer_id
INNER JOIN platforms ON platforms.id = orders.platform_id
INNER JOIN stocklocations ON stocklocations.id = platforms.stocklocation_id
LEFT JOIN productmodelvariants_stocklocations pmv_sl ON
pmv_sl.productmodelvariant_id = orderlines.productmodelvariant_id
AND pmv_sl.stocklocation_id = stocklocations.id
GROUP BY
orders.id
然后找出装运状态的位置。
答案 1 :(得分:1)
您的查询是针对任何给定订单在订单和货件之间进行笛卡尔联接。更好的方法是在进行连接之前将所有内容汇总到order_id
级别:
SELECT
#orders.*,
orders.id,
customers.lastname,
customers.priority,
shipments.status,
pmv_sl.productmodelvariant_id,
pmv_sl.nr AS pmv_nr,
COALESCE(ol.orderlines_nr_count, 0) AS orderlines_nr_count,
COALESCE(sl.shipment_lines_nr_count, 0) AS shipment_lines_nr_count
FROM orders
INNER JOIN customers ON customers.id = orders.customer_id
INNER JOIN platforms ON platforms.id = orders.platform_id
INNER JOIN stocklocations ON stocklocations.id = platforms.stocklocation_id
LEFT JOIN
(select order_id, SUM(orderlines.nr) as orderline_nr_count
from orderlines
group by order_id
) ol ON ol.order_id = orders.id
LEFT JOIN shipments ON shipments.order_id = orders.id
LEFT JOIN
(select order_id, SUM(shipment_lines.nr) shipment_lines_nr_count
from shipment_lines
group by order_id
) sl ON sl.shipment_id = shipments.id
# This JOIN, together with shipment_lines, makes the query suddenly very slow (probably because of all the SUM()'s)
LEFT JOIN productmodelvariants_stocklocations pmv_sl ON
pmv_sl.productmodelvariant_id = orderlines.productmodelvariant_id
AND pmv_sl.stocklocation_id = stocklocations.id
WHERE
orders.orderstatus_id = 2
AND orders.order_all_to_shipment = 0
GROUP BY
orders.id
这是一个近似值,因为我看到的唯一聚合函数是订单行和装运行。例如,如果每个订单有多个货件,您必须弄清楚如何将其压缩为一个状态(您的原始查询会随意选择一个,此查询也是如此)。
如果您只将group by
级别的表/子查询连接在一起,则不需要最后的order_id
。