views:

197

answers:

5

I need to select multiple records

I use

SELECT *
FROM `table`
WHERE `ID` =5623
OR `ID` =5625
OR `ID` =5628
OR `ID` =5621

this query run 4 times in every second whit php

is there a better and faster way for this ?

+12  A: 
SELECT *
FROM `table`
where ID in (5263, 5625, 5628, 5621) 

is probably better, but not faster.

anthares
Can you explain the reason why you think this is better.
gameover
Definitely more readable. However, I believe most query optimisers would generate the same execution plan, meaning this would be equivalent to the long-hand approach
AdaTheDev
I don't believe there is a performance difference, but it's more readable and error prove (if additional filters should be added).
anthares
I ran some tests and found that IN was a little faster, 10 or 15%. For one thing, the query is longer with OR.
fsb
@fsb that's interesting. I haven't read for such optimization. Is it possible the results to be subjective ?
anthares
Anthares, my tests were not very far reaching but the relative timing was consistent in a few different situations. I could not describe the results as "subjective" but I also don't read too much into them. My personal habit and preference is to use `IN` and the tests reassured me that I wasn't obviously better off using `OR`. And that's all I really wanted from those tests.
fsb
That's nice actually. I will try myself what impact it has. :) +1
anthares
+2  A: 
SELECT *
FROM `table`
WHERE `ID` IN (5623, 5625, 5628, 5621)

But four times per second is a lot. I would think about another approach that needs less database access.

Felix Kling
It's not a lot, normal Databases should be able to handle 20 times as many queries per second without significant load. You just have to set the indexes correctly.
dbemerlin
@dbemerlin: Ok, if you say so. Nevertheless for me sounds that the code could be improved and not doing the same query over and over again.
Felix Kling
+1  A: 
SELECT *
FROM `table`
WHERE `ID` in (5623, 5625, 5628, 5621)

While Researching this further I came across an interesting blog post that explains how to use a set to get faster SQL performance from In clauses, by creating list of ids into a Common Table Expression (CTE) and then joining on that.

So you could code the PHP equivalent of the following to get maximum performance.

DECLARE  @idList varchar(256) 
SET @idList = '5623, 5625, 5628, 5621'

;with ids (id) as
(
    SELECT value FROM UTILfn_Split(@idList,',')
)

SELECT     t.* 
FROM     table as t
INNER JOIN    ids
ON        t.ID = ids.id
Nicholas Murray
It is probably a viable approach if you have a comma-separated list as the input. If you already start with a list of numbers (as the question states), converting it to a string and then splitting back will likely cause too much overhead. I'd suggest sticking with a plain query with IN clause.
VladV
Yes of course, just another way of 'skinning the cat'.
Nicholas Murray
+4  A: 

On top of what the people stated (where id in):

1) iF there are a lot of IDs, better to stick them into a temp table and run a join with that temp table

2) Make sure your table has an index on id

3) If the real-timeliness of the data is not critical, put the query results in a cache on the application side

DVK
+1 for "temp table".
Frank Shearar
+1 for cache. Temp table approach would need careful benchmarking as the overhead in creating the table may negate any improvement.
AdaTheDev
Temp table had an unwritten assumption that the table is static and doesn't need to be re-populated every time for optimal performance. Good point
DVK
@DVK - Ah ok, yeah that would be better. I still favour your cache suggestion - that provides the best possible optimisation by a country mile.
AdaTheDev
MSSQL will automatically create a temp table for a long enough IN clause. Not sure about other database engines.
VladV
A: 

If you do

SELECT *
FROM `table`
WHERE `ID` IN (5623, 5625, 5628, 5621)

You should be fine, as long as the number of ID's don't get too big. I'd suggest you create an index for the ID's, so the query will perform faster.

Also, consider changing your logic, so you don't have to pass that many ID's

Marcos Placona