给定一些带有主键的表,例如:
CREATE TABLE Customers (
CustomerID int NOT NULL PRIMARY KEY,
FirstName nvarchar(50),
LastName nvarchar(50),
Address nvarchar(200),
Email nvarchar(260)
--...
)
Run Code Online (Sandbox Code Playgroud)
我们有一个唯一的主键CustomerID
。
传统上,我可能需要一些额外的覆盖索引;例如通过CustomerID
或快速找到用户Email
:
CREATE INDEX IX_Customers_CustomerIDEmail ON Customers
(
CustomerID,
Email
)
Run Code Online (Sandbox Code Playgroud)
这些是我几十年来创建的索引类型。
索引本身的存在是为了避免表扫描;它是一个覆盖索引,以帮助提高性能(该索引不是强制执行唯一性的约束)。
今天我想起了一点信息——SQL Server 可以使用以下事实:
以帮助它优化其查询执行。事实上,来自SQL Server 索引设计指南:
如果数据是唯一的并且您希望强制执行唯一性,则在相同的列组合上创建唯一索引而不是非唯一索引可为查询优化器提供附加信息,从而可以生成更高效的执行计划。在这种情况下,建议创建唯一索引(最好通过创建 UNIQUE 约束)。
鉴于我的多列索引包含主键,这个复合索引实际上是唯一的。这不是我特别需要 SQL Server 在每次插入或更新期间强制执行的约束;但事实是这个非聚集索引是唯一的。
将此事实上的唯一索引标记为实际唯一索引是否有任何优势?
在客户上创建唯一索引 IX_Customers_CustomerIDEmail ( 顾客ID, 电子邮件 ) …
在我的数据库中,我有一个带有两个索引的表。出于数据完整性原因,a、b 列上有一个唯一索引 #1。我有另一个索引 #2,其中包含 c、a、b 列,用于性能原因。我注意到这个索引#2 也是唯一的。
在我看来,索引#2 的唯一性似乎是多余的,因为索引#2 中不可能有重复值,而索引#1 中也不可能有重复值。我很想更改索引 #2,使其不再唯一,因为我想象数据库引擎可能会对索引 #2 中的 c、a、b 执行第二次检查,以确保每次插入行时这些列的唯一性,从而导致即使永远不会有重复的值,也会影响性能。它是否正确?
有没有办法删除 a、b 上的索引 #1 并保留 c、a、b 上的索引 #2,但仍然只对 a、b 列施加唯一约束,而不维护两个单独的索引?这将允许我只有一个索引包含所有三列,但仍然对 a、b 强制执行数据完整性约束。为了提高性能,我不需要在 a、b 上建立索引,因为我所有的选择查询都在 where 子句中包含 c 列。这是否是唯一约束而不是索引的用例?我认为数据库引擎基本上以相同的方式对待这两个构造(请参阅这篇文章:何时应该使用唯一约束而不是唯一索引?)。
请记住,索引不是冗余的,但索引的“唯一性”是冗余的。看起来让索引 #2 变得不唯一是理所当然的。但这会带来任何实际的性能提升吗?即使索引 #1 中的列完全包含在索引 #2 中,数据库是否检查两个索引的唯一性?
一些答案询问了用于从此表中选择数据的示例查询。以下是最常见的:
Select [some other columns] from table where c=1 and a=2
Select [some other columns] from table where c=1
Select [some other columns] from table where c=1 and a=2 and b=3
Run Code Online (Sandbox Code Playgroud)
这些查询通常包括选择不在任何索引中的许多其他列。
我们通常不会运行这样的查询:
Select [stuff] from table …
Run Code Online (Sandbox Code Playgroud) 我正在尝试将一行大小为 5k 的目标表更新为一行大小为 5k 的目标表。
由于它是一行,因此很容易知道行的实际大小:
select *
from sys.dm_db_index_physical_stats(DB_ID('RODS_HSD_ES'),
OBJECT_ID(N'TBL_BM_HSD_SUBJECT_AN_148_REPRO'), NULL, NULL, 'DETAILED')
Run Code Online (Sandbox Code Playgroud)
表自创建以来没有改变。没有看到它应该失败的任何原因。想法?
我发现过索引的大型堆表,例如有多个不同的非聚集索引和不同的列,但其中一些索引将(只有一个)主键列设置为它们的第一个索引列。
我进行了一些调查,使用了索引和查询,并得出了我希望专业人士确认的结论。
问题1:我说基于主键的多个索引而不是仅基于主键列的一个索引作为第一个也是唯一的索引列是无稽之谈,因为所有使用此pk进行过滤或加入的查询都返回只有一行?(假设额外的过滤、连接或选择的列作为包含列放入索引中以完全覆盖查询并避免 RID 查找)
问题 2:基于表主键的非聚集索引应该始终创建为 UNIQUE 索引,这样说对吗?(无论出于何种原因,该设置都是可选的,因为 sql server 应该已经知道包含 pk 的索引将是唯一的...)
index sql-server sql-server-2008-r2 index-tuning nonclustered-index