我正在SQL Server中运行查询,但突然开始运行非常慢。直到昨天,它过去的运行时间均不到1秒(或最多3秒)。突然之间,今天需要7到9分钟。我相信我的索引设置正确。
这是表的定义:
CREATE TABLE T_INDEX (
IndexId INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
[OwnerId] [varchar](20) NOT NULL DEFAULT (0),
[TicketId] [int] NOT NULL DEFAULT (0),
[TicketLogId] [int] NOT NULL DEFAULT (0),
[Type] [varchar](20) NOT NULL DEFAULT (''),
[CallId] [varchar](30) NULL,
[MessageId] [varchar](30) NULL,
[IndexRawDataId] [int] NOT NULL DEFAULT (0),
--INDEX/SEARCH
[CallTime] [datetime] NOT NULL,
[IndexMessageId] [int] NOT NULL DEFAULT (0),
[Direction] [varchar](20) NULL,
[Action] [varchar](20) NULL,
[Result] [varchar](30) NULL,
--GENERAL
[DefaultFileName] [varchar](100) NOT NULL DEFAULT '',
[TimeElapsedForTransfer] [int] NOT NULL DEFAULT (0),
[TimeElapsedForIndex] [int] NOT NULL DEFAULT (0),
[Duration] [int] NULL,
[HasR] [bit] NOT NULL DEFAULT (0), -- HAS RECORDING
[HasV] [bit] NOT NULL DEFAULT (0), -- HAS VOICEMAIL
[DeletedInd] [bit] NOT NULL DEFAULT (0),
[CompleteInd] [bit] NOT NULL DEFAULT (0)
)
我有这样定义的索引:
CREATE INDEX idx__T_INDEX__CallId
ON RingClone.dbo.T_INDEX (CallId)
GO
CREATE INDEX idx__T_INDEX__CallTime
ON RingClone.dbo.T_INDEX (CallTime)
GO
CREATE INDEX idx__T_INDEX__MessageId
ON RingClone.dbo.T_INDEX (MessageId)
GO
CREATE INDEX idx__T_INDEX__OwnerId
ON RingClone.dbo.T_INDEX (OwnerId)
GO
CREATE INDEX idx_T_INDEX_Dist
ON RingClone.dbo.T_INDEX (CompleteInd, DeletedInd)
INCLUDE (CallId, MessageId, OwnerId)
GO
CREATE INDEX nci_wi_T_INDEX_4E1CEC32C8F3DA763461240A854A7891
ON RingClone.dbo.T_INDEX (TicketId)
GO
我的查询如下:
DECLARE @ownerId varchar(20)
DECLARE @type varchar(20)
DECLARE @dateFrom datetime
DECLARE @dateTo datetime
SELECT TOP 50 T_INDEX.*
FROM T_INDEX
WHERE OwnerId=@ownerId
AND [Type]=@type
AND CallTime >= @dateFrom
AND CallTime <= @dateTo
ORDER BY CallTime DESC
此表中大约有400万条记录。并且该表的所有索引上的碎片小于2%。在发现速度缓慢之前,我刚刚更新了约5万行(更改了OwnerId
)。但是之后我立即重新索引了索引。此更新可能与突然的缓慢有关吗?我是否为此查询正确设置了索引?如果我将OwnerId
,'Type , and 'CallTime
组合在一起,是否会使查询运行得更快?还有什么我可以做的才能使它快速运行?
答案 0 :(得分:2)
AND(@dateFrom IS为NULL或CallTime> = @dateFrom)
请进行适当的查询-@dateFrom是否为null。动态生成SQL。
可替代地将查询优化为未知。
您轻而易举地遇到了一次参数嗅探,即一次确定查询计划并重新使用查询计划的情况。并且当其他查询计划更有意义时不会更新。
答案 1 :(得分:-1)
对于此查询:
SELECT TOP 50 T_INDEX.*
FROM T_INDEX
WHERE OwnerId = @ownerId AND
[Type] = @type AND
CallTime >= @dateFrom AND
CallTime <= @dateTo
ORDER BY CallTime DESC;
最佳索引是(OwnerId, Type, CallTime)
上的综合索引。前两列可以互换。
对于查询,您只有两个候选索引:(OwnerId)
和(CallTime)
(尽管SQL Server可能无法捕获该索引)。都不是最佳选择。
另一个潜在的问题是执行计划可能会被缓存。例如,如果代码在存储过程中,并且该过程在空表上进行了测试,则它可能不使用索引来缓存执行计划。这就是为什么with (recompile)
通常用于存储过程中的查询。