2008-12-04 92 views
0

我需要關於MySQL中的子選擇性能的建議。由於我無法更改的原因,我無法使用JOIN創建quesry過濾器,我只能在WHERE中添加另一個AND子句。MySQL子查詢性能問題?

什麼的peformance:

select tasks.* 
from tasks 
where 
    some criteria 
    and task.project_id not in (select id from project where project.is_template = 1); 

相比:

select tasks.* 
from tasks, project 
where 
    some criteria 
    and task.project_id = project.id and project.is_template <> 1; 

注意,這裏的項目數量相對較少whete is_template = 1,並有可能是大量的項目中is_template <> 1.

如果我不能改變任何東西,但沒有過濾器,還有其他方法可以實現同樣的結果嗎?

回答

5

我相信第二個效率更高,因爲它只需要一個選擇,但可以肯定的是,您應該解釋每個查詢並檢查結果。

EXPLAIN select tasks.* 
from tasks 
where 
    some criteria 
    and task.project_id not in (select id from project where project.is_template = 1); 

EXPLAIN select tasks.* 
from tasks, project 
where 
    some criteria 
    and task.project_id = project.id and project.is_template <> 1; 
+0

感謝您的EXPLAIN提示。 似乎在project.is_template上添加索引有很大幫助。 – Marko 2008-12-04 16:28:13

1

這兩者之間有多大的差異可能很大程度上取決於「某些標準」是什麼以及使用它提供的索引有哪些機會。但是請注意,如果有任務沒有項目,則它們在結果方面並不相同。二是相同的:

select tasks.* 
from tasks 
where 
    some criteria 
    and task.project_id in (select id from project where project.is_template <> 1); 
+0

「某些標準」幾乎可以減少返回記錄的總數。 task.project_id是必需的,所以這兩個查詢是等價的。 我選擇「不在」查詢原因然後子選擇返回小得多的記錄數然後它會如果我選擇「在」。 – Marko 2008-12-04 16:27:01

0

我認爲首先可以更好的擴展:

當你做一個連接,內部的mysql使一種由兩個表的臨時表的根據加盟加盟指定的條件。您沒有提供連接條件,因此它將創建一個臨時表,其中包含針對所有項目列出的所有任務。我很確定(但是請檢查解釋工具),它在應用任何where子句之前執行此操作。

結果:如果每個都有10個,它將有10 * 10行= 100。隨着數字的增加,您可以看到這個數字變大。然後它將這個臨時表的位置應用到該臨時表。

相反,子查詢只選擇每個表中的相關行。

但除非縮放是一個問題,我認爲它並不重要。

+0

沒有人贊同我....我想要一些討論。 – benlumley 2008-12-04 16:20:21

+0

嘗試一個簡單的解釋來證明自己錯了。 – ysth 2008-12-04 20:14:07

0

避免像MySQL版本< 6.0中的鼠疫這樣的子查詢,我懷疑你使用的是6.0,因爲它仍處於開發的alpha階段。 AFAIK,MySQL優化器根本不處理子查詢。一些主要的工作已經在6.0版本中改進了優化器,現在子查詢現在運行得好多了,但是這些改變還沒有流入5.0或5.1系列。