2014-03-12 65 views
0

這兩個表包含超過1m個記錄。使用「或」時優化MySQL查詢

該查詢需要15秒的運行,返回1條記錄(正確):

select orders.* 
     from orders 
    left join orders_details on orders.orderID=orders_details.orderID 
     where 
orders_details.trackingRef='GYD41624' 
or orders.orderID = (
select distinct orderID from orders_rebookings 
where trackingRef='GYD41624' 
) 
    group by orders.orderID 

而如果我與每個where條件運行查詢分開,然後各自非常快:

這需要0.0015秒(1個找到匹配):

select orders.* 
    from orders 
left join orders_details on orders.orderID=orders_details.orderID 
    where orders.orderID = (select distinct orderID from orders_rebookings where trackingRef='GYD41624')  
group by orders.orderID 

而這幾乎不需要花時間,沒有發現匹配(這是正確的):

select orders.* 
    from orders 
left join orders_details on orders.orderID=orders_details.orderID 
    where orders_details.trackingRef='GYD41624'  
group by orders.orderID 

所以,如果我有兩個非常快的查詢,我怎麼能使第一個包含「或」幾乎一樣快?

+0

- 將子查詢中的區別替換爲一個組 –

回答

0

您可以使用unionunion all將它們結合起來:

select o.* 
from orders o left join 
    orders_details od 
    on o.orderID = od.orderID 
where o.orderID = (select distinct orderID from orders_rebookings where trackingRef = 'GYD41624')  
group by o.orderID 
union 
select o.* 
from orders o left join 
    orders_details od 
    on o.orderID = od.orderID 
where od.trackingRef = 'GYD41624'  
group by o.orderID; 

union略效率較低,因爲它消除重複。

您的查詢也是危險的,因爲它有= (select . . .)。如果子查詢返回多行,則會出現錯誤。

不知這種形式會表現得更好:

select o.* 
from orders o 
where exists (select 1 from orders_details where o.orderID = od.orderID and od.trackingRef = 'GYD41624') or 
     exists (select 1 from orders_rebookings orr where o.orderID = orr.orderID and orr.trackingRef = 'GYD41624')  

你想在合適的索引(orders_details(orderId, TrackingRef)orders_rebookings(orderId, trackingRef))。

+0

嗨。好主意,我沒有考慮過這個。我的問題在於,我遇到的問題實際上包含在一個更大的查詢中。我只是將這一點孤立起來,以便清楚地說明這個例子。我可能能夠將聯合概念應用到大型查詢中,但我希望得到一些非常簡單的東西:-) – Chris