如何快速加入前1名

时间:2012-08-07 16:46:51

标签: sql sql-server

我有一个带有设备的表,另一个带有性能计数器的表。所以我有设备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

只是设置了提高速度的索引。

4 个答案:

答案 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