下面是一些細節,我試圖做一個SQLFiddle,但我不斷收到我的變量的錯誤。這在Sql Server 2008中有效。我的問題是,我怎樣才能讓我的查詢更快?我知道我在這裏做了許多錯誤的事情(重複的nester查詢),我希望能讓某人看一看,並幫助我從30分鐘的執行時間中解脫出來。 :-S我能做些什麼來加速這個SQL查詢?
查詢背後的基本思想是,在遊戲中我想找到所有在一段時間內沒有移動5個單位的玩家,他們在靜止的時候開了火併且沒有開火60分鐘在他們停止移動之前。
該查詢有效,但它是AND NOT EXISTS
子句,它放慢了抓取的速度,之後我添加了它需要16秒才能運行! 16秒還有很長的時間,因此,任何其他方面的改進,將不勝感激,但現在這個是我自己的POC遊戲(只是扔零碎東西收拾起來),16秒可以接受的...
DECLARE @n INT , @DistanceLimit INT
SELECT @n = 2 , @DistanceLimit = 5;
WITH partitioned
AS (SELECT * ,
CASE WHEN Distance < @DistanceLimit THEN 1
ELSE 0
END AS PartitionID
FROM EntityStateEvent
WHERE ExerciseID = '8B50D860-6C4E-11E1-8E70-0025648E65EC'
),
sequenced
AS (SELECT ROW_NUMBER() OVER (PARTITION BY PlayerID ORDER BY EventTime) AS MasterSeqID ,
ROW_NUMBER() OVER (PARTITION BY PlayerID, PartitionID ORDER BY EventTime) AS PartIDSeqID ,
*
FROM partitioned
),
filter
AS (SELECT MasterSeqID - PartIDSeqID AS GroupID ,
MIN(MasterSeqID) AS GroupFirstMastSeqID ,
MAX(MasterSeqID) AS GroupFinalMastSeqID ,
PlayerID
FROM sequenced
WHERE PartitionID = 1
GROUP BY PlayerID ,
MasterSeqID - PartIDSeqID
HAVING COUNT(*) >= @n
)
SELECT
DISTINCT (sequenced.PlayerID) ,
MIN(sequenced.EventTime) AS StartTime ,
MAX(sequenced.EventTime) AS EndTime ,
DATEDIFF(minute, MIN(sequenced.EventTime),
MAX(sequenced.EventTime)) AS StaticTime ,
Player.Designation AS 'Player'
FROM filter
INNER JOIN sequenced ON sequenced.PlayerID = filter.PlayerID
AND sequenced.MasterSeqID >= filter.GroupFirstMastSeqID
AND sequenced.MasterSeqID <= filter.GroupFinalMastSeqID
INNER JOIN Events ON Events.FiringPlayerID = sequenced.PlayerID
INNER JOIN Player ON Player.PlayerID = sequenced.PlayerID
AND Player.Force = 'FR'
AND NOT EXISTS (SELECT *
FROM Events
WHERE Events.FiringPlayerID = Player.PlayerID
GROUP BY Events.FiringTime
HAVING Events.FiringTime BETWEEN DATEADD(minute,
-60,
(SELECT
MIN(s.EventTime)
FROM
sequenced s
WHERE
s.PlayerID = filter.PlayerID
AND s.MasterSeqID >= filter.GroupFirstMastSeqID
AND s.MasterSeqID <= filter.GroupFinalMastSeqID
))
AND
(SELECT
MIN(s.EventTime)
FROM
sequenced s
WHERE
s.PlayerID = filter.PlayerID
AND s.MasterSeqID >= filter.GroupFirstMastSeqID
AND s.MasterSeqID <= filter.GroupFinalMastSeqID
))
INNER JOIN Player HitPlayer ON HitPlayer.PlayerID = Events.HitPlayerID
WHERE HitPlayer.[FORCE] = 'HO'
GROUP BY GroupID ,
sequenced.PlayerID ,
Events.FiringPlayerID ,
Events.FiringTime ,
Player.Designation
HAVING DATEDIFF(minute, MIN(sequenced.EventTime),
MAX(sequenced.EventTime)) > 5
AND Events.FiringTime BETWEEN MIN(sequenced.EventTime)
AND MAX(sequenced.EventTime)
ORDER BY StartTime
對於性能調整問題,您可能會在dba.stackexchange.com上得到更好的答案 – RichardTheKiwi
@RichardTheKiwi - 謝謝,我也會在那裏發帖。 – Faraday