Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL - how to use index in WHERE x IN (<subquery>)

I'm using this query to get all employees of {clients with name starting with lowercase "a"}:

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

Column employees.client_id is an int, with INDEX client_id (index_id). The subquery should IMHO return a list of id-s, which is then used in the WHERE clause.

When I EXPLAIN the query, the primary query uses no indexes (type:ALL). But when I EXPLAIN a list taken from the subquery (e.g. SELECT ... WHERE client_id IN (121,184,501)), the EXPLAIN switches to type:range, and this query gets faster by 50%.

How can I make the query use the index for the data returned by subquery - or, is there a more efficient way of retrieving this data? (Retrieving the id-list to application server, joining it and sending a second query is even more expensive here).

Thanks in advance.

like image 620
Piskvor left the building Avatar asked Dec 04 '08 09:12

Piskvor left the building


People also ask

Can we use index in where clause?

Indexes are also used to aid in filtering tables to assist in optimizing queries. The most obvious case of this is to optimize WHERE clauses. For example, the query "select * from employee where lastname = 'Jones'" results in a live cursor.

Can we use subquery in where clause in MySQL?

In MySQL subquery can be nested inside a SELECT, INSERT, UPDATE, DELETE, SET, or DO statement or inside another subquery. A subquery is usually added within the WHERE Clause of another SQL SELECT statement. You can use the comparison operators, such as >, <, or =.

How does MySQL choose which index to use?

If there is a choice between multiple indexes, MySQL normally uses the index that finds the smallest number of rows (the most selective index). If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to look up rows.

Does MySQL use index for in query?

Introduction to MySQL indexesAn index is a data structure used to locate data without scanning all the rows in a table for a given query. Indexes help retrieve data faster. Indexes are not visible to the users. They help speed up queries that require a search.


3 Answers

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

Should be more quicker, since the optimiser can choose the most efficient plan. In writing it your way with a sub-query, you're forcing it to do the steps in a certain order rather than letting it choose the optimal join order.

As a general rule sub-queries should be avoided since they will typically be less performant than a join query (though there are certain circumstances where they are unavoidable)

like image 107
cagcowboy Avatar answered Oct 06 '22 23:10

cagcowboy


Have you tried to do this with a JOIN and not a subselecct ?

SELECT employees.* FROM employees, clients WHERE employees.client_id = clients.id  AND clients.name LIKE 'a%';
like image 42
mat Avatar answered Oct 07 '22 00:10

mat


For a specific explanation on why

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

is slower than

SELECT * FROM employees WHERE client_id IN (1,2,3,4)

Check out this part of the MySQL manual, particuarly the third dot point: http://dev.mysql.com/doc/refman/5.0/en/subquery-restrictions.html. Also, this bug report.

like image 37
James Healy Avatar answered Oct 06 '22 23:10

James Healy