I have the following query:
SELECT
tl.*, d.*
FROM
TrackerLocations AS tl
inner join Trackers t on tl.TrackerId = t.TrackerId
inner join Devices d on t.UserId = d.UserId
WHERE
tl.ReceivedTime = (SELECT MAX(tl2.ReceivedTime) FROM TrackerLocations tl2 WHERE tl2.TrackerId = tl.TrackerId)
and tl.ReceivedTime >= DATEADD (MINUTE,-2,GETUTCDATE())
and d.OSType <> 3
and d.Notify = 1
...and for my surprise, it does not return the results in an acceptable time. First times I runned it in production environment, was like 3 seconds of execution. Now, it runs until timeout (inside C# application, 30 seconds).
The main purpose is: "give me the most recent locations from any tracker and info about it's users's devices, looking 2 minutes backwards".
Any hints about optimizing this query?
Thanks!
Indexes: Anywhere but where clause columns (ReceivedTime, OSType, Notify).
About the execution plan, it's a huge thing and it's not too familiar to me. Should I paste it here? :)
because I don't know what the execution plan looks like for this query I can only go on what I feel would help speed up the results.
beyond that I would try and use a CTE to limit the results being joined together something to the effect of (Not Tested):
Create indexes on
TrackerLocations.TrackerId
andTrackers.TrackerId
. AlsoDevices.UserId
andTrackers.UserId
for the 2ndJOIN
. Finally, look at creating an index onTrackerLocations.ReceivedTime
as well for theWHERE
clause.In general, the first place to look to optimize queries like this is checking to see if you have indexes on your join criteria. Also, if you have some sort of filter (
WHERE
clause), that could be another place to add an index.It's hard to say exactly where you need to optimize without looking at the query execution plan. A lot of factors can feed into it, including how many records are in each table. Don't go too crazy creating indexes, though -- they have a performance impact, for example when inserting new data. Best advice is to just test with different indexes, and see if the execution plan gives you some hints.
Since you are looking for the latest ReceivedTime within the last 2 minutes, you're going to want to create an index on
ReceivedTime
in DESC order. The DESC order part is important. It will also help with the MAX function. You can also try an index on(ReceivedTime DESC, TrackerID)
.I would suggest trying an index on (
TrackerId
,ReceivedTime
) and maybe justReceivedTime
as well. But, without profiling and an actual execution plan it's just a shot in the dark.