我在电子商务网站查询3个表格。
订单表:
id
order_number
name
etc...
order_lines表:
id
order_number
sku
quantity
etc.
产品表
id
sku
title
ship_by (INT)
etc.
order_number 将订单表链接到 order_lines 表。 SKU 将 order_lines 表链接到产品表。
请注意产品表中的 ship_by 列,这表示将向哪个供应商发货。查询需要为特定供应商提取订单。订单可能包含不同供应商销售的商品。
这是我设法凑齐的查询:
SELECT
orders.`order_number` as `orderId`,
orders.`shipping` as `fPostageCost`,
FROM_UNIXTIME(orders.`time`) as `dReceievedDate`,
(
CASE orders.`dob`
WHEN 'COURIER 3 DAY' THEN 'UK_SellersStandardRate'
WHEN 'COURIER 24 HOUR' THEN 'UK_OtherCourier24'
ELSE orders.`dob`
END
)
...(plus a number more)
FROM orders
INNER JOIN order_lines
ON orders.order_number = order_lines.order_number
WHERE
(
(SELECT COUNT(order_lines.sku)
FROM order_lines, products
WHERE order_lines.sku = products.sku
AND products.ship_by = 1
AND order_lines.order_number = orders.order_number) > 0
)
AND ( orders.`printed` = 'N' OR orders.`printed` IS NULL )
AND orders.status = 'Awaiting Despatch'
AND ( orders.payment_status = 'Success' OR orders.payment_status = 'Paypal Paid' OR orders.payment_status = 'Manual Payment' )
GROUP BY orders.`order_number`
ORDER BY orders.order_number ASC
执行查询大约需要7秒钟。
如果我删除了行' AND order_lines.order_number = orders.order_number'从第二个SELECT查询开始,它几乎立即执行,但如果没有这一行,它就不会像我需要的那样工作。
除了添加' ship_by'列到order_lines表(由于我不得不改变很多php代码,我不愿意这样做),有没有办法修改这个查询以加快它的速度?
查询是从PHP外部运行的,所以它必须是一个纯粹的mysql查询。
以下是查询的EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY order_lines ALL NULL NULL NULL NULL 9627 Using temporary; Using filesort
1 PRIMARY orders eq_ref order_idx order_idx 17 .order_lines.order_number 1 Using where
2 DEPENDENT SUBQUERY order_lines ALL NULL NULL NULL NULL 9627 Using where
2 DEPENDENT SUBQUERY products ref sku_2,sku,sku_3 sku_2 63 order_lines.prod_code 11 Using where
由于
答案 0 :(得分:1)
您的order_lines
表至少需要order_number
上的索引。我们需要查看架构以便最好地选择一个架构。也许复合指数会在其他领域加快速度。
但是在选择索引更改时,必须仔细权衡系统中的其他查询,以及对插入和更新速度的影响。
目标不应该是以90%为代价快速制作10%的应用程序。
要显示非常有用的信息,请发布show create table tableName
相关的表名。 (而不是自由地描述它,就像我的桌子有这个和那个)。我们需要查看订单,订单行,产品的架构。
答案 1 :(得分:1)
Idk表格在您的内联视图中有多大,但如果它很大则表示 它可能有助于使用联合而不必查询每个记录的视图。
类似的东西。
SELECT L1*
FROM
(SELECT
orders.`order_number` as `orderId`,
0 AS SKU_CNT,
orders.`shipping` as `fPostageCost`,
FROM_UNIXTIME(orders.`time`) as `dReceievedDate`,
(
CASE orders.`dob`
WHEN 'COURIER 3 DAY' THEN 'UK_SellersStandardRate'
WHEN 'COURIER 24 HOUR' THEN 'UK_OtherCourier24'
ELSE orders.`dob`
END
)
...(plus a number more)
FROM orders
INNER JOIN order_lines
ON orders.order_number = order_lines.order_number
WHERE ( orders.`printed` = 'N' OR orders.`printed` IS NULL )
AND orders.status = 'Awaiting Despatch'
AND ( orders.payment_status = 'Success' OR orders.payment_status = 'Paypal Paid' OR orders.payment_status = 'Manual Payment' )
UNION ALL
Select
0 AS ORDERID,
COUNT(OL.SKU) AS SKU_CNT,
0 as `fPostageCost`,
NULL as `dReceievedDate`,
...
FROM ORDER_LINES OL,
PRODUCTS PR
WHERE order_lines.sku = products.sku
AND products.ship_by = 1
AND order_lines.order_number = orders.order_number
GROUP BY ORDERID, ORDER_LINES_CNT, fPostageCost`, dReceievedDate`,
)L1
WHERE L1.SKU_CNT > 0
GROUP BY L1.`order_number`
ORDER BY L1.order_number ASC
答案 2 :(得分:0)
您可以将子查询替换为exists
:
WHERE EXISTS (SELECT 1
FROM order_lines ol2 JOIN
products p2
ON ol2.sku = p.sku AND
p2.ship_by = 1
ol.order_number = o.order_number
) AND
. . .
但是,您的查询片段未在外部查询中使用order_lines
。我怀疑你可以通过聚合摆脱它:
FROM orders o
WHERE EXISTS (SELECT 1
FROM order_lines ol2 JOIN
products p2
ON ol2.sku = p2.sku AND
p2.ship_by = 1
ol.order_number = o.order_number
) AND
. . .
这将至少返回所有订单信息 - 并且缺少聚合可能会简化查询的其他部分。如果某些版本的查询运行得很快,那么索引可能设置得合理。