Dam*_*ods 6 sql-server index-tuning
我已经提取了一个没有索引的 FK 列表。
如果 FK 没有专门的索引,但它是用于覆盖查询的更广泛索引的一部分,是否应该创建专门的索引?
例如,下面的 mytable 是一个 20 列的表,其中包含一个 varchar(255) 和其余的整数、日期时间或小整数。
它缺少索引
AdvertiserId
Dirty
MasterAdGroupId
Run Code Online (Sandbox Code Playgroud)
AdvertiserID 缺少外键索引,但 [advertiserID] 是索引的一部分,其中 [dirty]&[error] 是 smallint。这应该有自己的专用索引吗?
我应该删除其中一些索引并将它们与包含的列结合起来吗?然后为我的外键设置专用索引?
index_keys
-------------
[AdvertiserAdGroupId]
[AdvertiserHierarchyId]
[AdvertiserHierarchyId], [AdvertiserAdGroupId], [MasterAdGroupId]
[AdvertiserAdGroupCode]
[AdvertiserAdGroupId], [MasterAdGroupId], [AdvertiserId]
[AdvertiserId], [Dirty], [Error]
[MasterAdGroupId], [Deleted], [AdvertiserAdGroupId]
[AdvertiserHierarchyId], [Error], [AdvertiserAdGroupId], [MasterAdGroupId], [Deleted]
[Error], [AdvertiserHierarchyId], [Dirty], [AdvertiserAdGroupId]
[MasterAdGroupId], [AdvertiserAdGroupId], [AdvertiserHierarchyId]
[AdvertiserId], [AdvertiserAdGroupCode], [LastSyncedDate], [CreatedDate]
[AdvertiserId], [Deleted], [Paused], [AdvertiserAdGroupCode]
Run Code Online (Sandbox Code Playgroud)
如果 FK 上没有专用索引,但它是用于覆盖查询的更广泛索引的一部分,它们是否应该创建专用索引?
这取决于表的访问模式。如果该列被大量搜索(并且理想情况下是高度选择性的),那么是的,您绝对应该在该列上有一个索引,将该列作为定义中的第一个键列。
我应该删除其中一些索引并将它们与包含的列结合起来吗?然后为我的外键设置专用索引?
题主说的有点不清楚,你问的问题有点……糊涂,让我们退后一步。
在 SQL Server 2005+ 中,索引定义的三个最重要的部分是:
键列,确定索引排序顺序。这意味着键列的顺序非常重要,因为 SQL Server 通过在第一个键列中搜索值来使用索引,然后在第二个键列中等等。
包含的列,它们是标记到索引结构上的行数据的副本。指定的包含列的顺序无关紧要。
索引是唯一的吗?这意味着索引键只能包含列值的唯一组合。
(虽然这与手头的讨论无关,但为了完整起见,我将在此处提及:SQL Server 2008+ 引入了过滤索引的概念,它仅包括索引中满足谓词的行。)
您应该做的第一件事是指数整合。这涉及使用上述要点来组合共享共性的索引。
例如,考虑以下两个索引:
CREATE INDEX IX_1 ON [dbo].[t1](C1) INCLUDE(C3, C4);
CREATE INDEX IX_2 ON [dbo].[t1](C1, C2) INCLUDE(C5);
Run Code Online (Sandbox Code Playgroud)
这些索引共享前导键列C1。包含的列可以按任何顺序指定,因此这两个索引可以组合如下:
CREATE INDEX IX_3 ON [dbo].[t1](C1, C2) INCLUDE(C3, C4, C5);
Run Code Online (Sandbox Code Playgroud)
如果索引键的组成或其他属性不同,则必须非常小心。考虑这些索引:
CREATE INDEX IX_4 ON [dbo].[t1](C1, C3) INCLUDE(C4);
CREATE UNIQUE INDEX IX_5 ON [dbo].[t1](C1, C4) INCLUDE(C5);
Run Code Online (Sandbox Code Playgroud)
现在的决定并不那么容易。您必须根据您的工作负载、哪些查询命中表以及数据本身的选择性来确定要做什么。
因此,更直接地回答这个问题:如果您当前有一个或多个索引,其中感兴趣的列是这些索引中的第一个键列,则不必添加更多索引,因为您拥有的索引很有用。
如果该列被频繁搜索并且没有将该列作为第一键列的索引,则应该创建一个将该列作为第一键列的索引。(根据查询要求,您可能还想为键或包含的列指定其他列。)
如果不经常搜索该列,您可以将它包含在另一个索引(不是第一个键列)中:通过扫描包含该列的索引可能会满足查询。这不像索引查找那样有效(出于多种原因),但如果此操作不经常发生,并且在这种情况下的性能是可以接受的,那么您可能没问题。
请记住,创建索引是不是免费的-它们占用的数据空间,日志空间,高速缓冲存储器,并有可能减缓INSERT/ UPDATE/DELETE活动(话说回来,可以有其他的优势,以创建索引)。这是您必须为您的环境取得的平衡。