Reputation: 1453
I have a table with devices, and a second table with performance counters. So I have device A which has lets say 1000 entries in the performance counters table. I am trying to get all the devices, 2500 of them, and their most recent performance counter. I have used an Outer Apply, which does accomplish the desired results, but the query takes 5 minutes to execute.
Is this the best way to get the info I am looking for or is there a better way? Is the performance of this query normal, and I am just asking too much? I am thinking of creating a third 'temp' table nightly that will hold this data so I can display and query the info quickly. What are the best practices for something like this?
Here is my current query:
select * from Device D
OUTER APPLY
( select top 1 *
FROM PerformanceCounterValues
where instance_id = D.pkid
order by collection_time desc
) as tbl2
----- Solved ----
Here is my final actual query, and it works in 0 seconds.
SELECT pkid, D.IDDevice, D.IDHardware, H.IDRecorder, D.Name, D.Description, H.Name as HardwareName, H.URI, R.HostName, R.Name as RecorderInstance, tbl2.collection_time, tbl2.raw_value, tbl2.calculated_value
FROM [Surveillance].[dbo].[PerformanceCounterInstance] PCI
JOIN [Surveillance].[dbo].[Devices] D on D.IDDevice = (SELECT REPLACE(STUFF([instance_name],1,CHARINDEX('[',[instance_name]),''),']',''))
JOIN [Surveillance].[dbo].[Hardware] H on H.IDHardware = D.IDHardware
JOIN [Surveillance].[dbo].[Recorders] R on R.IDRecorder = H.IDRecorder
OUTER APPLY
( select top 1 *
FROM [Surveillance].[dbo].[PerformanceCounterValue]
where instance_id = PCI.pkid
order by collection_time desc
) as tbl2
where category_name = 'VideoOS Recording Server Device Storage'
and D.Enabled = 1
It was just setting up the index that made the speed increase.
Upvotes: 0
Views: 178
Reputation: 1453
Enabled Index and used this query:
SELECT pkid, D.IDDevice, D.IDHardware, H.IDRecorder, D.Name, D.Description, H.Name as HardwareName, H.URI, R.HostName, R.Name as RecorderInstance, tbl2.collection_time, tbl2.raw_value, tbl2.calculated_value
FROM [Surveillance].[dbo].[PerformanceCounterInstance] PCI
JOIN [Surveillance].[dbo].[Devices] D on D.IDDevice = (SELECT REPLACE(STUFF([instance_name],1,CHARINDEX('[',[instance_name]),''),']',''))
JOIN [Surveillance].[dbo].[Hardware] H on H.IDHardware = D.IDHardware
JOIN [Surveillance].[dbo].[Recorders] R on R.IDRecorder = H.IDRecorder
OUTER APPLY
( select top 1 *
FROM [Surveillance].[dbo].[PerformanceCounterValue]
where instance_id = PCI.pkid
order by collection_time desc
) as tbl2
where category_name = 'VideoOS Recording Server Device Storage'
and D.Enabled = 1
Upvotes: 0
Reputation: 115530
I'm not sure whaty indexing would be best for the outer apply
query, but you can try adding an index on (instance_id, collection_time)
for this one:
SELECT
d.* --- whatever columns you need from Device
, p.* --- and from PerformanceCounterValues
FROM Device AS d
JOIN
( SELECT instance_id,
MAX(collection_time) AS max_collection_time
FROM PerformanceCounterValues
GROUP BY instance_id
) AS grp
ON grp.instance_id = d.pkid
JOIN PerformanceCounterValues AS p
ON p.instance_id = grp.instance_id
AND p.collection_time = grp.max_collection_time ;
It would also help if you added the execution plan of your query in your question.
Upvotes: 1
Reputation: 198
Try to select top one directly on the join, i have about 20,000 corresponding entries in one talbe for which i want to fetch the first entry time from a Logs table. my query executes in less than 2 sec(MsSql 2008)
select D.pkid, pvc.*
from Device D
join PerformanceCounterValues as pcv on pcv.PrimaryKey = (SELECT top(1) PrimaryKey From PerformanceCounterValues WHERE instance_id = D.pkid ORDER BY collection_time )
Upvotes: 0
Reputation: 45096
try
select D.pkid, max(PerformanceCounterValues.collection_time)
from Device D
join PerformanceCounterValues
on PerformanceCounterValues.instance_id = D.pkid
group by D.pkid
Upvotes: 1