2008-12-04 23 views
8

我使用這個查詢來獲取所有員工{客戶名稱以小寫的「a」}:MySQL的 - 如何使用索引,其中X IN(<subquery>)

SELECT * FROM employees 
    WHERE client_id IN (SELECT id FROM clients WHERE name LIKE 'a%') 

employees.client_id是int,與INDEX client_id (index_id)。子查詢應該IMHO返回一個id-s列表,然後在WHERE子句中使用它。

當我EXPLAIN查詢,主查詢使用沒有索引(type:ALL)。但是,當我EXPLAIN 從子查詢(例如SELECT ... WHERE client_id IN (121,184,501)),則EXPLAIN切換到type:range截取的列表,並且該查詢由50%變快。

我怎樣才能使查詢使用子查詢返回的數據指標 - 或者是有這個檢索數據的更有效的方法? (檢索id-list到應用程序服務器,加入它併發送第二個查詢在這裏更加昂貴)。

在此先感謝。

回答

12
SELECT employees.* 
FROM employees, clients 
WHERE employees.client_id = clients.id 
AND clients.name LIKE 'a%'; 

應該更快,因爲優化器可以選擇最有效的計劃。在與一個子查詢寫你的方式,你強迫它做的步驟按照一定的順序,而不是讓它選擇最佳的連接順序。

一般來說子查詢應避免使用,因爲它們通常會比連接查詢少高性能的(儘管有某些情況下,他們是不可避免的)

+0

也可以使用INNER JOIN語法。 – MarkR 2008-12-04 10:07:41

+0

我見過查詢優化器真的錯了,並且返回ID的子查詢加載速度更快。但這是一個非常具體的案例。 請參閱:http://www.benlumley.co.uk/2008/06/25/mysql-query-optimiser-left-lacking/,如果你有興趣的細節。 – benlumley 2008-12-04 10:15:59

5

你試過用JOIN做到這一點,不是次要的?

SELECT employees.* FROM employees, clients WHERE employees.client_id = clients.id AND clients.name LIKE 'a%'; 
2

值得指出的是,對於每個數據庫管理系統來說,連接性能都不如子查詢。它確實爲MySQL做。

0
select * from X as _x where 
    exists(select * from Y as _y where _y.someField = _x.someField) 

應該做的伎倆給你們。)

1
SELECT e.* 
FROM employees e 
WHERE EXISTS ( 
    SELECT 1  
    FROM clients c 
    WHERE c.id = e.client_id 
    AND c.name LIKE 'a%' 
) 

可以重寫使用EXISTS 查詢。在MySQL中,它肯定會提高性能。欲瞭解更多優化幫助,您可以參考:MySQL-In-Query-Optimization