我有一个带有设备的表,另一个带有性能计数器的表。所以我有设备A,它可以在性能计数器表中输入1000个条目。我试图获得所有设备,其中2500个,以及他们最近的性能计数器。我使用了外部应用,它可以完成所需的结果,但查询需要5分钟才能执行。
这是获取我正在寻找的信息的最佳方式还是有更好的方法?这个查询的性能是否正常,我只是要求太多?我想在每晚创建一个第三个“临时”表来保存这些数据,这样我就可以快速显示和查询信息。对于这样的事情,最佳做法是什么?
这是我当前的查询:
select * from Device D
OUTER APPLY
( select top 1 *
FROM PerformanceCounterValues
where instance_id = D.pkid
order by collection_time desc
) as tbl2
-----解决了----
这是我最后的实际查询,它在0秒内有效。
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
只是设置了提高速度的索引。
答案 0 :(得分:1)
尝试
select D.pkid, max(PerformanceCounterValues.collection_time)
from Device D
join PerformanceCounterValues
on PerformanceCounterValues.instance_id = D.pkid
group by D.pkid
答案 1 :(得分:1)
我不确定whaty索引最适合outer apply
查询,但您可以尝试在此(instance_id, collection_time)
上添加索引:
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 ;
如果您在问题中添加了查询的执行计划,也会有所帮助。
答案 2 :(得分:0)
尝试直接在连接上选择前一个,我在一个talbe中有大约20,000个相应的条目,我想从Logs表中获取第一个输入时间。我的查询在不到2秒的时间内执行(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 )
答案 3 :(得分:0)
启用索引并使用此查询:
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