Blu*_*eft 6 t-sql sql-server optimization sql-server-2005 query-optimization
我们有许多机器以零星的间隔将数据记录到数据库中.对于每条记录,我想获得此录制和上一次录制之间的时间段.
我可以使用ROW_NUMBER执行此操作,如下所示:
WITH TempTable AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Machine_ID ORDER BY Date_Time) AS Ordering
FROM dbo.DataTable
)
SELECT [Current].*, Previous.Date_Time AS PreviousDateTime
FROM TempTable AS [Current]
INNER JOIN TempTable AS Previous
ON [Current].Machine_ID = Previous.Machine_ID
AND Previous.Ordering = [Current].Ordering + 1
Run Code Online (Sandbox Code Playgroud)
问题是,它真的很慢(在一个有大约10k条目的表上几分钟) - 我尝试在Machine_ID和Date_Time上创建单独的指示,以及一个连接索引,但没有任何帮助.
无论如何重写此查询以更快?
给定的ROW_NUMBER()分区和顺序要求索引(Machine_ID, Date_Time)在一次传递中满足:
CREATE INDEX idxMachineIDDateTime ON DataTable (Machine_ID, Date_Time);
Run Code Online (Sandbox Code Playgroud)
如果有的话,Machine_ID和Date_Time上的单独索引将帮助很少.
它与这个版本相比如何?:
SELECT x.*
,(SELECT MAX(Date_Time)
FROM dbo.DataTable
WHERE Machine_ID = x.Machine_ID
AND Date_Time < x.Date_Time
) AS PreviousDateTime
FROM dbo.DataTable AS x
Run Code Online (Sandbox Code Playgroud)
还是这个版本?:
SELECT x.*
,triang_join.PreviousDateTime
FROM dbo.DataTable AS x
INNER JOIN (
SELECT l.Machine_ID, l.Date_Time, MAX(r.Date_Time) AS PreviousDateTime
FROM dbo.DataTable AS l
LEFT JOIN dbo.DataTable AS r
ON l.Machine_ID = r.Machine_ID
AND l.Date_Time > r.Date_Time
GROUP BY l.Machine_ID, l.Date_Time
) AS triang_join
ON triang_join.Machine_ID = x.Machine_ID
AND triang_join.Date_Time = x.Date_Time
Run Code Online (Sandbox Code Playgroud)
两者都可以通过Machine_ID,Date_Time上的索引表现最佳,并且对于正确的结果,我假设这是唯一的.
你没有提到隐藏在*中的东西,有时候意味着很多,因为Machine_ID,Date_Time索引通常不会覆盖,如果你有很多列,或者他们有很多数据,...