views:

94

answers:

4

Suppose I have a 2 column table (id, flag) and id is sequential. I expect this table to contain a lot of records. I want to periodically select the first row not flagged and update it. Some of the records on the way may have already been flagged, so I want to skip them.

Does it make more sense if I store the last id I flagged and use it in my select statement, like

select * from mytable where id > my_last_id order by id asc limit 1

or simply get the first unflagged row, like:

select * from mytable where flagged = 'F' order by id asc limit 1

Thank you!

+2  A: 

Option two is the only one that makes sense unless you know that you're always going to process records in sequence!

ninesided
I know that I will always process them in order.
artsince
he is using an `order by` on the id key .. so it is always in sequence..
Gaby
@Gaby, I realise this, but there's nothing saying that there couldn't be unprocessed records with an id below that of the "latest processed id". This would leave you with holes in your data that could never be filled based on the logic of the first query.
ninesided
@ninesided, you are correct.. logic-flaw on my part ..
Gaby
+3  A: 

If you create an index on flagged, retrieving an unflagged row should be pretty much an instant operation. If you always update them sequentially, then the first method is fine though.

reko_t
A: 

Assuming MySQL, this one:

SELECT  *
FROM    mytable
WHERE   flagged = 'F'
ORDER BY
        flagged ASC, id ASC
LIMIT 1

will be slightly less efficient in InnoDB and of same efficiency in MyISAM, if you have an index on (flagged, id).

InnoDB tables are clustered on the PRIMARY KEY, so fetching the first record in id does not require looking up the table.

In MyISAM, tables are heap-organized, so the index used to police the PRIMARY KEY is stored separately from the table.

Note the flagged in the ORDER BY clause may seem to be redundant, but it is required for MySQL to pick the correct index.

Also, the composite index should be on (flagged, id) even in InnoDB (which implicitly includes the PRIMARY KEY into each index).

Quassnoi
what is the point of ordering by `flagged` since it is the filter ( *with one allowed value in the resultset* )... it is useless...
Gaby
@Gaby: this will help `MySQL` to pick the correct index.
Quassnoi
@Quassnoi, if it is an intrinsic issue with the implementation then i declare my ignorance on it :) it just seems pretty un-intuitive.. (edit: thanks for the additional info, makes more sense now :) )
Gaby
My table is InnoDB and id is primary key...
artsince
@artsince: in absolute terms, both queries will be instant (order of magnitude of milliseconds) and the difference will be imperceptible, as long as you create the indexes. However, the first query (with only `id`) will be one page lookup faster in `InnoDB`, FWIW.
Quassnoi
I suppose that depending on what values are possible for "flag" you'd need to change whether the index is ascending or descending on that column?
ninesided
@ninesided: `MySQL` does not support descending indexes. You should change direction in `ORDER BY` and directions of all columns should match for the index to be usable.
Quassnoi
A: 

You could use

Select Min(Id) as 'Id'
From dbo.myTable
Where Flagged='F'

Assuming the Flagged = 'F' means that it is not flagged.

Barry
.. but he is asking for `*` not just the id..
Gaby
Ah yes of course. Although I am not sure why you would <code>*</code> in this scenario.
Barry