2015-09-15 66 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