2008-12-04 18 views
8

yılında endeksi nasıl kullanılacağı:MySQL - NEREDEN x IN (<subquery>) Ben {küçük "a" ile başlayan adıyla müşterilerine} tüm çalışanlara almak için bu sorguyu kullanıyorum

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

Sütun employees.client_id bir olduğunu int, INDEX client_id (index_id) ile. Alt sorgu, IMHO'nun daha sonra WHERE maddesinde kullanılan bir id-s listesi döndürmesi gerekir.

Sorguyu EXPLAIN yaptığımda, birincil sorgu hiçbir dizin kullanmaz (type:ALL). Ancak, alt sorgudan alınan bir liste (ör. SELECT ... WHERE client_id IN (121,184,501)), EXPLAINEXPLAINEXPLAIN, type:range olarak değişir ve bu sorgu% 50 daha hızlı olur.

Sorguyu, alt sorgu tarafından döndürülen veri için dizini nasıl kullanabilirim - veya bu verileri almanın daha verimli bir yolu var mı? (Kimlik listesini uygulama sunucusuna geri almak, katılmak ve ikinci bir sorgu göndermek burada daha da pahalı).

Şimdiden teşekkürler.

cevap

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

Optimiser en verimli planı seçebileceğinden daha hızlı olmalıdır. Yazarken, bir alt sorgu ile yolunuzu, en uygun birleştirme sırasını seçmesine izin vermek yerine, adımları belirli bir sırayla yapmaya zorlarsınız. Genel bir kural alt sorgular gibi

(bunlar kaçınılmaz olan bazı durumları vardır gerçi)

+0

INNER JOIN sözdizimini de kullanabilir. – MarkR

+0

Sorgu en iyi duruma getiricinin gerçekten yanlış anladığı ve kimlikleri döndüren bir alt sorgunun daha hızlı olduğu durumlar gördüm. Ama bu gerçekten özel bir durumdu. Bakınız: http://www.benlumley.co.uk/2008/06/25/mysql-query-optimiser-left-lacking/ Ayrıntılar ile ilgileniyorsanız. – benlumley

5

Bir JOIN ile bunu denedi ve var bunlar genellikle bir sorgu katılmak daha az başarılı olacaktır çünkü kaçınılmalıdır alt alan değil mi?

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

Var olan her DBMS için geçerli değildir alt sorgular daha iyi performans katılır belirtmekte fayda olduğunu. Yine de MySQL için yapar.

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

sizin için hile yapmak mı. MySQL'de, kesinlikle bir performans iyileştirmesi sağlar. Daha fazla optimizasyon konusunda yardım almak isterseniz bakın olabilir: MySQL-In-Query-Optimization

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

Sen MEVCUT kullanarak sorgu yazabilirsiniz);

+0

Herhangi bir alt sorgu kullanmanın MySQL ile bir gelişme olduğunu düşünmüyorum. – mat