Cas*_*ins 1 database-design sql-server index-tuning sql-server-2012
我正在尝试提高由实体框架自动生成的特定查询的性能。我已经通过 SSMS 运行了查询,它建议创建两个缺失的索引。有问题的表:
CREATE TABLE [dbo].[PackageEvents]
(
[EventID] [int] NOT NULL IDENTITY(1, 1),
[PackageID] [char] (24) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[EventDescription] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[EventDate] [datetime] NOT NULL,
[UserName] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Notes] [varchar] (max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[IsSynchronized] [bit] NOT NULL CONSTRAINT [DF_AmazonPackageEvents_IsSynchronized]
DEFAULT ((0)),
[LastSyncDate] [datetime] NULL,
[Version] [timestamp] NOT NULL
)
Run Code Online (Sandbox Code Playgroud)
SSMS 建议了以下两个索引:
CREATE NONCLUSTERED INDEX [IX_IsSynchronized] ON [dbo].[PackageEvents]
([IsSynchronized]) INCLUDE ([PackageID])
CREATE NONCLUSTERED INDEX [IX_Covering] ON [dbo].[PackageEvents] ([PackageID])
INCLUDE ([EventDate], [EventDescription], [EventID], [IsSynchronized], [LastSyncDate],
[Notes], [UserName], [Version])
Run Code Online (Sandbox Code Playgroud)
我没有发布我正在优化的查询,因为它非常糟糕(由实体框架生成)并且几乎无法读取。通常,查询会查找 IsSynchronized = 0 的任何行并返回这些行。
有没有办法将这两个索引组合成一个索引,以提供相同或更好的性能优势?如果没有确切的查询,这个问题是不可能回答的吗?
编辑:唯一存在的索引是主键 EventID 上的聚集索引。
我搜索了生成的实体框架查询。以下 where 子句出现 4 次,但总是以相同的形式出现:
WHERE EXISTS (SELECT
1 AS [C1]
FROM [dbo].[AmazonPackageEvents] AS [Extent46]
WHERE ([Project30].[PackageID] = [Extent46].[PackageID]) AND
(0 = [Extent46].[IsSynchronized])
)
Run Code Online (Sandbox Code Playgroud)
这似乎归结为
WHERE PackageID=@PackageID AND IsSynchronized=0
Run Code Online (Sandbox Code Playgroud)
好吧,你可以考虑一个过滤索引 - 如果你总是在寻找IsSynchronized = 0
这个数字应该相对较小的行,那么不要考虑这两个索引,而是考虑这个:
CREATE NONCLUSTERED INDEX [IX_NotSynchronized]
ON [dbo].[PackageEvents] ([PackageID])
INCLUDE ([EventDate], [EventDescription], [EventID],
[LastSyncDate], [Notes], [UserName], [Version])
WHERE IsSynchronized = 0;
Run Code Online (Sandbox Code Playgroud)
当然,如果查询必须查找数据(如果行数很小,应该非常有效),您可能希望使其更小并测试以查看影响的差异,因此 - 假设PackageID
是聚类键:
CREATE NONCLUSTERED INDEX [IX_NotSynchronized]
ON [dbo].[PackageEvents] ([PackageID])
WHERE IsSynchronized = 0;
Run Code Online (Sandbox Code Playgroud)
与完整索引相比,维护此索引的开销可能非常值得节省空间,特别是如果它仅用于优化此查询(或至少是查询模式)。
不过,过滤索引并不神奇。JNK 提出了以下一些限制:
使用过滤索引的注意事项 - 统计数据可能无法在没有维护的情况下保持最新,并且您需要对某些设置(如 QUOTED IDENTIFIER 和 ANSI NULLS)使用“标准”值。这些都是小问题,但如果您在插入索引的会话中设置错误,插入将失败。
您还需要阅读这些帖子:
如果您不想使用过滤索引,您可以测试这些变体:
CREATE NONCLUSTERED INDEX [IX_Covering_try1] ON [dbo].[PackageEvents]
([PackageID], IsSynchronized)
INCLUDE ([EventDate], [EventDescription], [EventID],
[LastSyncDate], [Notes], [UserName], [Version]);
CREATE NONCLUSTERED INDEX [IX_Covering_try2] ON [dbo].[PackageEvents]
(IsSynchronized, [PackageID])
INCLUDE ([EventDate], [EventDescription], [EventID],
[LastSyncDate], [Notes], [UserName], [Version]);
Run Code Online (Sandbox Code Playgroud)
(很长一段时间以来,我认为在键中包含 BIT 列是一种浪费,但 Martin Smith 展示了一个效果很好的案例 - 值得一试。我现在找不到帖子了。)
如果没有您的完整架构、数据、查询模式等,我们只能指导您并让您在您的环境中测试我们的建议。我们不能说,“叮!这个对你有用!”
归档时间: |
|
查看次数: |
316 次 |
最近记录: |