2017-04-24 60 views
1

由於某些原因,這些2個等價查詢的成本差別很大。Mysql上奇怪的查詢成本或

select p.* 
from properties p 
where owner_phone = '+598 99 554 718' 
    or p.id in (
     select pop.property 
     from property_other_phones pop 
     where pop.phone='+598 99 554 718' 
    ) 

具有下列費用: enter image description here

雖然這另一個:

select p.* 
from properties p 
where 
    p.id in (
     select id 
     from properties 
     where owner_phone = '+1 781-953-6380' 
    ) 

union select p.* 
from properties p 
where 
    p.id in (
     select pop.property 
     from property_other_phones pop 
     where pop.phone='+1 781-953-6380' 
    ) 

有此完全不同的費用: enter image description here

你們是否有一些線索?

Conext:MySQL的16年7月5日

+0

的查詢不看我也一樣。 –

+0

這兩個查詢返回的結果可能看起來是等價的,但這兩個查詢看起來與MySQL不同*歷史上,MySQL繼續使用'OR'謂詞生成不太理想的查詢計劃的傳統。 – spencer7593

回答

2

歷史上,MySQL優化生成與OR謂詞查詢不理想的計劃。這就是爲什麼我們經常使用UNION/UNION ALL子查詢來代替OR謂詞。

問題表明這兩個查詢是等價的。我同意這兩個查詢模式返回的結果可能看起來是等價的。但就MySQL優化器查看它們的方式以及優化器可用的操作而言,這兩種查詢模式顯着不同。

對於問題中顯示的兩個查詢,MySQL優化程序爲每個查詢選擇的執行計劃看起來都是該課程的標準。 (爲OR查詢生成的計劃可能會不太理想。這可能是不幸的,但它不是真正的「怪」。)

假設idproperties主鍵(或唯一鍵),我會選擇這樣的查詢模式:

SELECT p.* 
    FROM properties p 
    JOIN (SELECT i.id 
      FROM properties i 
      WHERE i.owner_phone = '+1 781-953-6380' 
      UNION 
     SELECT pop.property AS id 
      FROM property_other_phones pop 
      WHERE pop.phone  = '+1 781-953-6380' 
     ) q 
    ON q.id = p.id 

作爲另一種選擇,我可能會考慮:

SELECT p.* 
    FROM properties p 
WHERE p.owner_phone   = '+1 781-953-6380' 
UNION ALL 
SELECT q.* 
    FROM properties q 
    JOIN property_other_phones pop 
    ON pop.property = q.id 
WHERE pop.phone    = '+1 781-953-6380' 
    AND NOT (q.owner_phone <=> '+1 781-953-6380') 
+0

謝謝!檢查了這些建議並完美地工作。在第一個查詢中,我仍然沒有完全理解全表掃描的原因:(如果你可以點亮這個,將會被理解爲: – Ignacio

+0

'OR'導致全表掃描,所用的技巧spencer是將'OR'轉換爲'UNION';它的每個部分都可以非常有效地運行 –

+0

@Ignacio:MySQL優化器是有限的;它只能選擇一個索引用於訪問;對於第一個條件,MySQL可以使用索引範圍掃描來滿足'owner_phone ='謂詞,但是這個索引並沒有真正幫助'id IN()'謂詞......來檢查MySQL是否需要對每一行進行評估,相反,如果MySQL選擇使用一個帶有id的前導列來定位滿足第二個條件的行的索引,仍然有第一個條件需要處理......並且我們又回到了檢查每一行的地方,如果MySQL必須檢查每一個翻轉行,那麼它是滿的掃描... – spencer7593