2017-07-14 419 views
-1

我正在編寫一個大型查詢,它必須從多個表中查詢數據。 (11桌)MySql加入Where條件,執行順序和性能的條件

我正在重寫腳本,它有巨大的性能問題。 該腳本使數千個(有時是數萬個)小型查詢而不是幾個大型查詢。該查詢可能需要數小時才能完成,並可能消耗大量內存。 它現在的工作方式是這樣的。 1)來自db的查詢匹配事件 2)即返回500行。 3)遍歷所有的行,並且從每個相關聯的表

foreach(rows as row) { 
     row.user = /* query db for user data */ 
     row.products = /* query db for product data */ 
     row.productMeta = /* query db for additional data */ 
     ... and so on, for 11 tables 
    } 

取附加數據因此,500行將創建500×11查詢。

我的目標是重寫腳本,使其以 的方式在1-2個大型查詢中加入並評估MySql服務器端的所有條件。

這是問題。 什麼是使這個大型查詢最有效的方法。 它是否有所作爲,如果我在 評估條件加入ON子句,比較外部WHERE子句。

i.e 

SELECT * FROM events 
    INNER JOIN users ON users.event_id = events.id AND <condition 1> 
    INNER JOIN products ON products.event_id = events.id AND <condition 2> 
    LEFT JOIN inventory ON inventory.event_id = events.id AND <condition 3> 

VS 

SELECT * FROM events 
    INNER JOIN users ON users.event_id = events.id 
    INNER JOIN products ON products.event_id = events.id 
    LEFT JOIN inventory ON inventory.event_id = events.id 
WHERE 
    <condition 1> 
    AND <condition 2> 
    AND <condition 3> 

VS 

making a few more queries to pre-filter the events, then join 

$userIds = "make separate join to return event ids where users.event_id = events.id AND <condition 1>" 
$productIds = "make separate join to return event ids where products.event_id = events.id AND <condition 2>" 

Then: 

SELECT * FROM events 
    INNER JOIN users ON users.event_id = events.id 
    INNER JOIN products ON products.event_id = events.id 
    LEFT JOIN inventory ON inventory.event_id = events.id 
WHERE 
    events.id IN ($userIds) OR events.id IN ($productIds) 

PS:所有相關列索引

+0

選中此項:https://dev.mysql.com/doc/refman/5.7/en/left-join-optimization.html –

+0

如果您需要左連接並且condition1,2,3涉及左連接表中的列你應該只使用第一個select ...左連接表的列成爲內連接 – scaisEdge

+0

'in' CAN(並非總是)比存在或連接慢 – xQbert

回答

0

是的,你是正確的,以避免500次* 11的查詢。

對於JOIN,無論您輸入ON還是WHERE都無關緊要。 但是把它放在WHERE中是「正確的」。

對於LEFT JOIN,它確實事。所以,堅持ON這樣的原則只有這些表是如何關聯的,以及WHERE過濾器。

​​有時候阻礙了Optimizer選擇最佳索引的能力。所以,暫時不使用這種方法。

OR幾乎總是壞表現。儘可能避免它。一種解決方法是使用UNION

如果有一個GROUP BY你沒有提到,可能還有一些其他問題。

底線:選項2 似乎是最好的。

無論最終查詢是什麼樣子,您可能需要重新訪問表上的索引。見my cookbook

你只給出了一個問題的答案,所以我只能給出一個建議。也許你想更接近於說明Option 2方法。並且包括SHOW CREATE TABLE