[英]MySQL - how to use index in WHERE x IN (<subquery>)
我正在使用此查詢來獲取名稱以小寫字母“a”開頭的{客戶端}的所有員工:
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檢索到應用程序服務器,加入它並發送第二個查詢在這里更加昂貴)。
提前致謝。
SELECT employees.*
FROM employees, clients
WHERE employees.client_id = clients.id
AND clients.name LIKE 'a%';
應該更快,因為優化者可以選擇最有效的計划。 在使用子查詢編寫它時,您強制它按特定順序執行步驟,而不是讓它選擇最佳連接順序。
作為一般規則,應該避免子查詢,因為它們通常不如連接查詢高性能(盡管在某些情況下它們是不可避免的)
您是否嘗試使用JOIN
而非子選擇來執行此操作?
SELECT employees.* FROM employees, clients WHERE employees.client_id = clients.id AND clients.name LIKE 'a%';
有關原因的具體說明
SELECT * FROM employees WHERE client_id IN (SELECT id FROM clients WHERE name LIKE 'a%')
比...慢
SELECT * FROM employees WHERE client_id IN (1,2,3,4)
查看MySQL手冊的這一部分,特別是第三點: http : //dev.mysql.com/doc/refman/5.0/en/subquery-restrictions.html 。 此外,這個錯誤報告 。
值得指出的是,對於每個DBMS而言,連接執行優於子查詢並不適用。 但它確實適用於MySQL。
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
select * from X as _x where
exists(select * from Y as _y where _y.someField = _x.someField)
應該為你做的伎倆;)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.