我在SQL Server中的表看起来像这样:的SQL Server索引/ SQL性能增强
CREATE TABLE [dbo].[FCT_RawEvents](
[EquipID] [int] NOT NULL,
[EventTimeStamp] [int] NOT NULL,
[EventMilliSeconds] [smallint] NULL,
[EventID] [int] NOT NULL,
[EventOn] [bit] NOT NULL,
[JobID] [int] NULL,
[FirstEvent] [bit] NULL,
[OperatorId] [int] NULL,
[Suppressed] [bit] NULL,
[ManualOverride] [bit] NULL
)
这包含事件,即要么打开或关闭(EventOn =真,EventOn = FALSE)。现在我需要在给定的时间获得所有'活动'(未被抑制)的事件。我有一些SQL可以工作,但是由于这个表的行数在几百万,所以它运行速度很慢(5个equipIds需要10秒)。
这就是:
DECLARE @StartDateTime datetime = '2013/01/01'
DECLARE @csvEquipIds nvarchar(MAX) = '5,6,7,8'
DECLARE @StartTimeStamp int = dbo.GetSecondsFromDate(@StartDateTime)
DECLARE @StartMilliSeconds smallint = DATEPART(Ms, @StartDateTime)
DECLARE @EquipIds TABLE (EquipId int)
INSERT INTO @EquipIds(EquipId) SELECT EquipID FROM dbo.getEquipmentIDs(null,@csvEquipIds)
SELECT dbo.getDateFromSeconds(EventTimeStamp), * FROM
( SELECT re.EquipID,EventTimeStamp,EventMilliSeconds,EventID,eventon,
ROW_NUMBER() OVER (PARTITION BY re.EquipId,EventID ORDER BY EventTimeStamp DESC,EventMilliSeconds DESC) AS RowNo
FROM dbo.FCT_RawEvents re
JOIN @EquipIds eq
ON eq.EquipId = re.EquipID
WHERE (re.EventTimeStamp < @StartTimeStamp OR(re.EventTimeStamp = @StartTimeStamp AND re.EventMilliSeconds <= @StartMilliSeconds)) AND re.EventID > 0
AND (re.Suppressed IS NULL)-- OR re.Suppressed = 0)
) ev
WHERE RowNo = 1 AND EventOn = 1
ORDER BY EquipID,EventID, EventTimeStamp desc, EventMilliSeconds desc
执行计划表明,80%的时间花费在排序,这是分区/订单窗口的功能。
我绝不是INDEX专家,但已经添加了这些:
CREATE CLUSTERED INDEX [IX_Clustered] ON [dbo].[FCT_RawEvents]
(
[EquipID] ASC,
[EventTimeStamp] DESC,
[EventMilliSeconds] DESC,
[EventID] ASC,
[EventOn] DESC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_EquipEventTime] ON [dbo].[FCT_RawEvents]
(
[EquipID] ASC,
[EventID] ASC,
[EventTimeStamp] DESC,
[EventMilliSeconds] DESC
)
INCLUDE ([EventOn]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_Suppressed] ON [dbo].[FCT_RawEvents]
(
[Suppressed] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
看来,那种被扫描表,在这里我真的希望它的很大一部分'回顾'直到找到第一个匹配的事件。
任何指针将不胜感激,无论是通过使用索引或改进SQL。
我猜你在桌子上有一些索引。你也可以添加它们吗?我在屏幕截图上看到两个“Table Scan”,看起来这个黄色长方形隐藏了某种“seek”。避免表扫描。 [这个链接]也许可以提供帮助。 – Yaroslav
你的第二个索引看起来很大程度上是多余的(取决于你的查询工作量当然) –
尝试使用临时表而不是表变量;你也可以摆脱缩放的UDF,getDateFromSeconds? –