2013-04-05 90 views
0

我在寫一個存儲過程,它的功能是獲取許多參數(由最終用戶填充)並執行搜索。但是,如果參數沒有值,則不應將其包含在WHERE子句中。爲此,我本人對參數進行檢查作爲or子句的第一部分,像這樣:通過連接表上的參數檢查減慢MySQL查詢

... WHERE (param1 = '' OR field1 = param1) AND (param2 = '' OR field2 = param2) ... 

我已經然後將這一成普通的SELECT語句,像這樣:

SELECT * 
FROM table1 t1 
WHERE (param1 = '' OR t1.field1 = param1) 

請注意,爲了清楚起見,本例中我只包含了一個參數。真正的查詢包含多個參數和字段比較。

這工作正常並且運行很快(例如,'真正的'查詢返回約0.5秒的結果)。

到目前爲止這麼好。但是,當引入一個連接表時,事情就會出錯。例如,如果我執行下面的查詢,它需要更長的時間(3-4秒的實際查詢):

SELECT * 
FROM table1 t1 

LEFT JOIN table2 t2 
ON t1.table2Id = t2.id 

WHERE (param1 = '' OR t2.field1 = param1) 

請注意該參數現在被比作場的連接表(表2)。

請注意,在這兩個例子中,運行查詢時,我已經確保參數1中填充了值。

現在,如果我刪除上述WHERE子句的param1 = '' OR部分,它的運行速度與以前的未連接查詢相同。

我的表中使用的字段都沒有索引,儘管我已經嘗試了這一點,但對於我遇到的問題沒有任何影響。

那麼,有沒有人可以向我解釋爲什麼第一個查詢(單個表)工作的很快,但第二個查詢(連接表)花費的比例過長?

非常感謝提前。

回答

0

我終於通過對錶2的去除LEFT JOIN並用簡單JOIN按照下面替換它解決了這個問題:

SELECT * 
FROM table1 t1 

JOIN table2 t2 
ON t1.table2Id = t2.id 

WHERE (param1 = '' OR t2.field1 = param1) 

說實話,絕對沒有理由讓它成爲LEFT JOIN。我只是沒有想到!無論如何,非常感謝埃文和邁克爾的幫助和建議(以及他們的超級快速反應)。

0

嘗試添加第一個條件作爲JOIN的一部分,看看是否有幫助。

SELECT * 
FROM table1 t1 

LEFT JOIN table2 t2 
ON t1.table2Id = t2.id AND 
t2.field1 = param1 
+0

謝謝埃文。我按照你的建議嘗試過,但是現在當param1有一個值時我沒有得到結果。 – 2013-04-05 12:07:36

+0

@JohnP查看更新 - 只刪除最後一行 – 2013-04-05 13:22:20

+0

對不起埃文。不幸的是,現在我不能沒有價值地'過濾'任何參數。 – 2013-04-05 13:35:19

0

您可以嘗試製作一個視圖,並在該視圖中使用該視圖的結果。

CREATE VIEW `VW_my_simple_table_view_name` AS SELECT * 
FROM table1 t1 
WHERE (param1 = '' OR t1.field1 = param1) 

,然後查詢會是這個樣子(可能需要適應)

SELECT * 
FROM VW_my_simple_table_view_name t1 

LEFT JOIN table2 t2 
ON t1.table2Id = t2.id 

WHERE (t2.field1 = param1) 
+0

感謝您的建議,但我不確定這種方法是否有效。例如,我將參數與table2中的字段進行了比較,實際上我並沒有與table1的任何字段進行比較。 – 2013-04-05 12:15:39