Ben
Ben

Reputation: 4867

MySQL Slow SELECT Query

I have a query, which is something along the lines of:

SELECT * FROM table1
WHERE confirmed = 0
AND resource = 123
AND id IN (
  SELECT id FROM table2 WHERE resource = 123
  AND added > 1440000000
)

It takes nearly 3 minutes to run, but I have no idea why. Here's why I'm confused...

SELECT id FROM table2 WHERE resource = 123
AND added > 1440000000

There are no results for this sub-query. Not a single one. So, I thought if I did this:

SELECT * FROM table1
WHERE confirmed = 0
AND resource = 123
AND id IN (
 0
)

It should take about the same time to run. Except it doesn't - it instantly returns 0 results as expected. What's going on? What's the different to comparing an empty query result to 0?

The row numbers are pretty low too. I've run an explain and it's using the confirmed key for table 1 and the primary key from table 2. The row count is 5500 / 20000 respectively.

Any ideas would be very gratefully received! Thank you!

Upvotes: 1

Views: 82

Answers (2)

Rick James
Rick James

Reputation: 142208

IN ( SELECT ... ) Optimizes very poorly before 5.6. 5.6 is better, but still not great.

JOIN ( SELECT ... ) must be computed first, and requires a temp table. So it is not as good as a plain JOIN as below.

SELECT  *
    FROM  table1 AS t1
    JOIN  table2 AS t2 ON t2.id = t1.id
    WHERE  t1.confirmed = 0
      AND  t1.resource = 123
      AND  t2.resource = 123
      AND  t2.added > 1440000000 

And have

table2:  INDEX(resource, added)
table1:  INDEX(resource, confirmed)

Upvotes: 1

Gordon Linoff
Gordon Linoff

Reputation: 1269443

Your query would run faster using an explicit join. If the subquery doesn't return duplicate values:

SELECT t1.*
FROM table1 t1 JOIN
     (SELECT id FROM table2 WHERE resource = 123 AND added > 1440000000
     ) t2
     ON t1.id = t2.id
WHERE confirmed = 0 AND resource = 123;

Also, MySQL is often better optimizing NOT EXISTS:

SELECT t1.*
FROM table1 t1
WHERE confirmed = 0 AND resource = 123 AND
      NOT EXISTS (SELECT 1
                  FROM table2 t2
                  WHERE t2.id = t1.id AND t2.resource = 123 AND t2.added > 1440000000
                 );

This query will run faster with an index on table2(id, resource, added).

Upvotes: 1

Related Questions