Reputation: 121
I have the following simple query:
SELECT TOP 1 message
FROM Log l
WHERE l.id_fk = '##Guid##'
AND l.id_category IN ('Category 1', 'Category 2')
ORDER BY l.timestamp DESC
The execution time on large Log tables without an nonclustered descending index on timestamp
is very long because the complete list has to be ordered first to get the top 1 entry.
Is it possible to get rid of the order by statement or is creating the index completely the best solution?
Upvotes: 0
Views: 72
Reputation: 94914
The query is fine. You want this index:
CREATE INDEX idx ON log (id_fk, id_category, timestamp DESC);
Or even this:
CREATE INDEX idx ON log (id_fk, id_category, timestamp DESC, message);
Thus the greatest timestamp for the two categories can be quickly looked up. With the latter index it is not even necessary to read the table.
Upvotes: 0
Reputation: 15075
Try this:
SELECT TOP 1 message
FROM (select l.timestamp,l.message
FROM Log l
WHERE l.id_fk = '##Guid##'
AND l.id_category IN ('Category 1', 'Category 2')
) x
ORDER BY x.timestamp DESC
Just written off top of head, basically the inner query filters your data conditions to a smaller set, then orders to get the top 1
Upvotes: 0
Reputation: 1269753
I think the fastest approach is this more complex query:
SELECT TOP (1) message
FROM ((SELECT TOP 1 l.message, l.timestamp
FROM Log l
WHERE l.id_fk = '##Guid##' AND
l.id_category = 'Category 1'
ORDER BY l.timestamp DESC
) UNION ALL
(SELECT TOP 1 l.message, l.timestamp
FROM Log l
WHERE l.id_fk = '##Guid##' AND
l.id_category = 'Category 2'
ORDER BY l.timestamp DESC
)
) l
ORDER BY timestamp DESC
This can take advantage of an index on log(id_fk, id_category, l.timestamp)
. Unfortunately, SQL cannot use the index on timestamp
with IN
.
Upvotes: 1