【发布时间】:2013-08-17 21:10:53
【问题描述】:
我有一个数据库,其中只有一个表Logs,其中包含列:
-
Id(PK Clustered, int, not null), -
ServiceName(nvarchar(255), not null) 和其他一些列,如 -
TaskVariant(nvarchar(1024)), -
Source(nvarchar(1024))。
我在ServiceName 列上创建了一个索引INDEX_SERVICENAME(非唯一,非集群),其中包括除Id, ServiceName 之外的所有列。
- 数据库大小约为 4 GB。
- 表包含大约 3 500 000 行。
- 表包含大约 1400000 行,Source = N'IpJob'。
- 表包含大约 240 万行,TaskVariant = N'Ip'。
- 表包含大约 600 000 行,ServiceName = '1' 和 TaskVariant = N'Ip'。
- 表包含大约 350 000 行,ServiceName = '1' 和 Source = N'IpJob'。
问题:
我想通过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
【问题讨论】:
-
你的表真的没有聚集索引吗?真的真的很糟糕......它应该有!最好在
Id上。许多操作在聚簇表上比在堆上快得多。请参阅 Kim Tripp 的优秀博文 The Clustered Index Debate Continues...,其中详细解释了这些事情 -
你能显示两个查询的执行计划吗?
-
抱歉,列 ID 是主聚集键。我将更新问题以添加此信息。
标签: sql sql-server sql-server-2008