MySQL: How to simplify a "IN" query
I know that I have to avoid to use "IN" clause, but I don't know how to do in this case. The scenario is this: from PHP I get a list of values and then I construct a query like this:
SELECT id FROM
( SELECT * FROM `tips` r
LEFT JOIN (SELECT tip FROM `tips_showed` WHERE user='8') AS a ON r.id=a.tip
WHERE a.tip IS NULL ) AS t
WHERE t.id IN
('3','4','5','2','6','7','8','9','10','18',
'11','12','13','14',开发者_如何学JAVA'15','16','17','20') LIMIT 1
This makes my site very slow (because it is executed each time a user visits it). How can make it faster?
I believe you can simplify the query to:
SELECT t.id
FROM `tips` t
LEFT JOIN `tips_showed` a
ON t.id = a.tip
AND a.user = '8'
WHERE a.tip IS NULL
AND t.id IN ('3','4','5','2','6','7','8','9','10','18',
'11','12','13','14','15','16','17','20')
LIMIT 1
Using NOT EXISTS
instead of the LEFT JOIN
may also buy you some additional performace. Try each and compare.
SELECT t.id
FROM `tips` t
WHERE t.id IN ('3','4','5','2','6','7','8','9','10','18',
'11','12','13','14','15','16','17','20')
AND NOT EXISTS(SELECT NULL
FROM `tips_showed` a
WHERE a.tip = t.id
AND a.user = '8')
LIMIT 1
Get rid of sub-selects. The IN()
clause is perfectly ok.
Following AJ's request for writing down the corrected query:
SELECT `r`.`id`
FROM `tips` AS `r`
LEFT JOIN `tips_showed` AS `a`
ON (`a`.`user`='8' AND `r`.`id`=`a`.`tip`)
WHERE `r`.`id` IN ('3','4','5','2','6','7','8','9','10','18',
'11','12','13','14','15','16','17','20')
AND `a`.`tip` IS NULL
LIMIT 1
The above code is not tested and may contain some serious mistakes (was written ad hoc) - if you find any, please give me feedback in the comments.
Plus
Do not forget to add proper indexes.
I noticed that the IN is a sequential series of the values
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 and an extra number 20.
You can just replace the IN here with
WHERE (r.id = 20) OR (r.id BETWEEN 2 AND 18)
Much faster, because you only have to do 3 comparisons worst case.
If you have random values
Use a temp memory table.
With a hash primary key.
And do an inner join on the primary hash key.
Time this and tell me how much faster it went :-)
精彩评论