2015-09-15 67 views
2

我在查询电子商务网站中的3个表。加快缓慢3表MYSQL查询

订单表:

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 table to products table。

注意产品表中的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秒钟执行查询。

如果我从第二个SELECT查询中删除行'AND order_lines.order_number = orders.order_number',它几乎立即执行,但是没有这一行,它不能正常工作,因为我需要它。

除了将'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 

感谢

回答

1

order_lines表需要上order_number指数至少是。我们需要查看模式以最好地选择一个模式。也许一个综合指数会在其他领域加快速度。

但是在选择索引更改时,必须仔细权衡系统中的其他查询以及对插入和更新速度的影响。

的目标不应该是使你的应用程序快10%,在90的

费用要显示非常有用的信息,发布show create table tableName为相关的表名。 (而不是用手描述它,就像我的桌子上有这个那样)。我们需要查看订单,订单,产品的模式。

Create Index

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 
     . . . 

这至少会返回所有的订单信息 - 和缺乏聚集可以简化查询的其他部分。如果某些版本的查询运行得很快,那么索引可能是合理的。

+0

感谢@drew&snowsprinkle为您的答案。我第一次尝试戈登的建议,并根据我改变了SQL现在阅读: '选择 o.order_number ...等 从接单O,ORDER_LINES醇,商品P WHERE ol.sku = p.sku AND (o.'printed' ='N'或o'''inting' is NULL) AND o.status ='等待发货' AND(o。 payment_status ='成功'或o.payment_status ='Paypal付款'或o.payment_status ='手动付款') GROUP BY o.'order_number' ORDER BY o.order_number ASC' – Jason

+0

...现在查询完成在0.05秒内。快140倍。辉煌! 我需要提高我的mysql知识。有时间寻找我认为的新书。再次感谢。 – Jason

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