8

我正在使用此查询来获取 {clients 的所有员工,其名称以小写“a”开头}:

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

Columnemployees.client_id是一个 int,带有INDEX client_id (index_id). 恕我直言,子查询应该返回一个 id-s 列表,然后在 WHERE 子句中使用。

当我EXPLAIN查询时,主查询不使用索引(type:ALL)。但是,当我EXPLAIN 从子查询(例如SELECT ... WHERE client_id IN (121,184,501))中获取一个列表时,EXPLAIN切换到type:range,并且该查询的速度提高了 50%。

如何使查询使用子查询返回的数据的索引 - 或者,是否有更有效的方法来检索这些数据?(将 id-list 检索到应用程序服务器,加入它并发送第二个查询在这里更加昂贵)。

提前致谢。

4

6 回答 6

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

应该更快,因为优化器可以选择最有效的计划。在使用子查询以您的方式编写它时,您是在强制它按特定顺序执行这些步骤,而不是让它选择最佳连接顺序。

作为一般规则,应避免子查询,因为它们的性能通常低于连接查询(尽管在某些情况下它们是不可避免的)

于 2008-12-04T09:32:48.537 回答
5

您是否尝试过使用 aJOIN而不是 subselectect 来做到这一点?

SELECT employees.* FROM employees, clients WHERE employees.client_id = clients.id  AND clients.name LIKE 'a%';
于 2008-12-04T09:33:14.980 回答
4

有关原因的具体解释

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 。另外,这个错误报告

于 2009-07-22T02:54:58.713 回答
2

值得指出的是,连接性能优于子查询并不适用于每个 DBMS。它确实适用于 MySQL。

于 2008-12-04T12:12:07.687 回答
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

于 2008-12-04T13:23:53.533 回答
0
select * from X as _x where 
  exists(select * from Y as _y where _y.someField = _x.someField)

应该为您解决问题;)

于 2008-12-04T12:17:16.617 回答