此查询运行速度非常快(<100毫秒):
SELECT TOP (10)
[Extent2].[CompanyId] AS [CompanyId]
,[Extent1].[Id] AS [Id]
,[Extent1].[Status] AS [Status]
FROM [dbo].[SplittedSms] AS [Extent1]
INNER JOIN [dbo].[Sms] AS [Extent2]
ON [Extent1].[SmsId] = [Extent2].[Id]
WHERE [Extent2].[CompanyId] = 4563
AND ([Extent1].[NotifiedToClient] IS NULL)
如果我只添加一个时间过滤器,则需要太长时间(22秒!):
SELECT TOP (10)
[Extent2].[CompanyId] AS [CompanyId]
,[Extent1].[Id] AS [Id]
,[Extent1].[Status] AS [Status]
FROM [dbo].[SplittedSms] AS [Extent1]
INNER JOIN [dbo].[Sms] AS [Extent2]
ON [Extent1].[SmsId] = [Extent2].[Id]
WHERE [Extent2].Time > '2015-04-10'
AND [Extent2].[CompanyId] = 4563
AND ([Extent1].[NotifiedToClient] IS NULL)
我尝试在[Time]
表的Sms
列上添加索引,但优化器似乎没有使用索引。尝试使用With (index (Ix_Sms_Time))
;但令我惊讶的是,它需要更多的时间(29秒!)。
这是实际的执行计划:
两个查询的执行计划相同。这里提到的表具有5M到8M行(索引<1%碎片并且统计信息被更新)。我在16核32GB内存Windows 2008 R2机器上使用MS SQL Server 2008R2)
答案 0 :(得分:0)
只有在客户端过滤器运行后强制时间过滤器启动时,它是否有帮助?
FI就像在这个例子中一样:
;WITH ClientData AS (
SELECT
[E2].[CompanyId]
,[E2].[Time]
,[E1].[Id]
,[E1].[Status]
FROM [dbo].[SplittedSms] AS [E1]
INNER JOIN [dbo].[Sms] AS [E2]
ON [E1].[SmsId] = [E2].[Id]
WHERE [E2].[CompanyId] = 4563
AND ([E1].[NotifiedToClient] IS NULL)
)
SELECT TOP 10
[CompanyId]
,[Id]
,[Status]
FROM ClientData
WHERE [Time] > '2015-04-10'
答案 1 :(得分:0)
使用以下Sms
(按此顺序)在Index Key Columns
上创建索引:
您可能需要也可能不需要将Id
添加为Included Column
。
答案 2 :(得分:0)
您的时间列是什么数据类型? 如果是日期时间,请尝试转换您的&#39; 2015-04-10&#39;进入等效的数据类型,以便它可以使用索引。
Declare @test datetime
Set @test='2015-04-10'
然后修改你的条件:
[Extent2].Time > @test
如果存在数据类型不匹配,则sql server会隐式转换为匹配的数据类型。任何函数或强制转换操作都会阻止使用索引。
答案 3 :(得分:0)
我和@JonTirjan在同一条轨道上,只有时间的索引导致很多关键查找,所以你应该至少尝试一下:
create index xxx on Sms (Time, CompanyId) include (Id)
或
create index xxx on Sms (CompanyId, Time) include (Id)
如果Id是您的聚簇索引,则include子句中不需要它。如果您的数据的重要部分属于CompanyID 4563,那么也可以将其作为包含列。
您在实际计划中看到的百分比只是基于行数假设的估计值,因此有时完全错误。查看实际行数/执行次数+统计数据IO输出应该可以让您了解实际发生的情况。
答案 4 :(得分:0)
我想到了两件事:
答案 5 :(得分:0)
我发现SmsId
表上的外键列(SplittedSms
)上没有索引。我做了一个,似乎第二个查询几乎和现在的第一个一样快。
现在执行计划:
感谢大家的努力。