我有一个只有一个表Logs
的数据库,其中包含列:
Id
(PK Clustered,int,not null),ServiceName
(nvarchar(255),非null)和其他一些列,如TaskVariant
(nvarchar(1024)),Source
(nvarchar(1024))。我在INDEX_SERVICENAME
列上创建了一个索引ServiceName
(非唯一,非群集),其中包含除Id, ServiceName
以外的所有列。
问题:
我希望通过ServiceName
和TaskVariant
或Source
选择表格过滤中的所有列。我的原始查询用于选择按Source
过滤的最后100个项目是:
SELECT TOP (100)
[Filter1].[Id] AS [Id],
[Filter1].[Date] AS [Date],
[Filter1].[Data] AS [Data],
[Filter1].[ServiceName] AS [ServiceName],
[Filter1].[LogLevel] AS [LogLevel],
[Filter1].[StackTrace] AS [StackTrace],
[Filter1].[TaskVariant] AS [TaskVariant],
[Filter1].[Source] AS [Source],
[Filter1].[Message] AS [Message]
FROM ( SELECT [Extent1].[Id] AS [Id], [Extent1].[Date] AS [Date], [Extent1].[Data] AS [Data], [Extent1].[ServiceName] AS [ServiceName], [Extent1].[LogLevel] AS [LogLevel], [Extent1].[StackTrace] AS [StackTrace], [Extent1].[TaskVariant] AS [TaskVariant], [Extent1].[Source] AS [Source], [Extent1].[Message] AS [Message], row_number() OVER (ORDER BY [Extent1].[Id] DESC) AS [row_number]
FROM [dbo].[Logs] AS [Extent1]
WHERE (@serviceName = [Extent1].[ServiceName]) AND (@source = [Extent1].[Source])
) AS [Filter1]
WHERE [Filter1].[row_number] > 0
ORDER BY [Filter1].[Id] DESC
此查询的工作时间非常快〜00:00:00。
但是当我尝试按TaskVariant
过滤时,查询需要~00:02:18分钟(下一个查询)。
SELECT TOP (100)
[Filter1].[Id] AS [Id],
[Filter1].[Date] AS [Date],
[Filter1].[Data] AS [Data],
[Filter1].[ServiceName] AS [ServiceName],
[Filter1].[LogLevel] AS [LogLevel],
[Filter1].[StackTrace] AS [StackTrace],
[Filter1].[TaskVariant] AS [TaskVariant],
[Filter1].[Source] AS [Source],
[Filter1].[Message] AS [Message]
FROM ( SELECT [Extent1].[Id] AS [Id], [Extent1].[Date] AS [Date], [Extent1].[Data] AS [Data], [Extent1].[ServiceName] AS [ServiceName], [Extent1].[LogLevel] AS [LogLevel], [Extent1].[StackTrace] AS [StackTrace], [Extent1].[TaskVariant] AS [TaskVariant], [Extent1].[Source] AS [Source], [Extent1].[Message] AS [Message], row_number() OVER (ORDER BY [Extent1].[Id] DESC) AS [row_number]
FROM [dbo].[Logs] AS [Extent1]
WHERE (@serviceName = [Extent1].[ServiceName]) AND (@taskVariant = [Extent1].[TaskVariant])
) AS [Filter1]
WHERE [Filter1].[row_number] > 0
ORDER BY [Filter1].[Id] DESC
问题:为什么第二个查询的执行速度要慢得多,以及如何解决这个问题?
非常感谢你的建议。
执行计划1
答案 0 :(得分:1)
索引的工作方式类似于层次结构/树,其级别与其中的列相对应。
因此,如果您的索引位于ServiceName, TaskVariant
,则可以快速过滤到特定的ServiceName
,因为这是树中的顶级。
但是,如果您尝试按TaskVariant
进行过滤,则现在必须仔细阅读整个索引:您不能只跳转到特定的TaskVariant
,因为相同的TaskVariant
将是在不同的ServiceName
s。
如果要对TaskVariant进行过滤,则需要以TaskVariant
开头的另一个索引。注意:不要只为每一列创建完整的索引:每个索引占用额外的空间,需要在UPDATE
和INSERT
上进行更多的工作
答案 1 :(得分:0)
您看到的执行时间的差异主要是由于第一个具有索引而第二个没有。至于为什么它有这么大的差异,可能是因为有一个索引,这意味着值被排序。
由于值已经过排序,因此您可以使用非常有效的字符串搜索算法,这些算法可以在过滤数量级时减少操作次数。
此外,还有许多其他特征会影响这一点。整个索引可能在内存中,而表数据则不是,因此第一个查询中的过滤可以在内存中完成,而不会触及磁盘,而另一个可能没有。