Sql server 何时使用覆盖索引、复合索引和唯一列索引
假设我在SQL Server 2008中有下表:Sql server 何时使用覆盖索引、复合索引和唯一列索引,sql-server,database-design,indexing,rdbms,Sql Server,Database Design,Indexing,Rdbms,假设我在SQL Server 2008中有下表: ProfileID int //identity; index: unique, primary key, clustered ClientID int RegionID int ProfileName nvarchar(50) 第2列和第3列通过外部关系链接到各自的表 假设我最常见的问题是: SELECT ProfileID, ProfileName FROM Profiles WHERE Client
ProfileID int //identity; index: unique, primary key, clustered
ClientID int
RegionID int
ProfileName nvarchar(50)
第2列和第3列通过外部关系链接到各自的表
假设我最常见的问题是:
SELECT ProfileID, ProfileName
FROM Profiles
WHERE ClientID = ? AND RegionID = ?
ORDER BY ProfileName
什么索引系统最适合
如果我在(ProfileID,ProfileName)上放置了一个覆盖索引,那么这将终止默认聚集索引,因为覆盖索引必须是非聚集索引,但至少满足查询的返回部分
如果我将主键保持原样,并独立索引ClientID和RegionID,这将提供3个必须由RDBMS维护的索引,加上表扫描仍然需要返回ProfileName,因为它没有被覆盖。这似乎很重
这是一个简单的案例,说明索引计划的复杂性。对于此查询:
SELECT ProfileID, ProfileName
FROM Profiles
WHERE ClientID = ? AND RegionID = ?
ORDER BY
ProfileName
CREATE INDEX ix_profiles_region_client_name__id ON (RegionID, ClientID, ProfileName) INCLUDE (ProfileID)
您应该创建以下索引:
CREATE INDEX ix_profiles_region_client_name ON (RegionID, ClientID, ProfileName)
在(RegionID,ClientID)
的单个值内,记录在ProfileName
上进行排序,这样记录将被排序,无需额外排序
由于ProfileID
是一个主键集群
,它隐式地包含在每个索引记录中,因此不需要在索引定义中明确指定它
如果它不是聚集键,则需要将其添加到索引中,以覆盖此查询:
SELECT ProfileID, ProfileName
FROM Profiles
WHERE ClientID = ? AND RegionID = ?
ORDER BY
ProfileName
CREATE INDEX ix_profiles_region_client_name__id ON (RegionID, ClientID, ProfileName) INCLUDE (ProfileID)
对于此查询:
SELECT ProfileID, ProfileName
FROM Profiles
WHERE ClientID = ? AND RegionID = ?
ORDER BY
ProfileName
CREATE INDEX ix_profiles_region_client_name__id ON (RegionID, ClientID, ProfileName) INCLUDE (ProfileID)
您应该创建以下索引:
CREATE INDEX ix_profiles_region_client_name ON (RegionID, ClientID, ProfileName)
在(RegionID,ClientID)
的单个值内,记录在ProfileName
上进行排序,这样记录将被排序,无需额外排序
由于ProfileID
是一个主键集群
,它隐式地包含在每个索引记录中,因此不需要在索引定义中明确指定它
如果它不是聚集键,则需要将其添加到索引中,以覆盖此查询:
SELECT ProfileID, ProfileName
FROM Profiles
WHERE ClientID = ? AND RegionID = ?
ORDER BY
ProfileName
CREATE INDEX ix_profiles_region_client_name__id ON (RegionID, ClientID, ProfileName) INCLUDE (ProfileID)
@我的朋友,你回来了。我猜你的意思是“…也保留主索引”?不仅仅是这一个索引?我有两个问题:1)我认为(ClientID,RegionID…)会更好,因为ClientID是最独特的列(好吧,我在我的问题中没有提到这一点,是的)。我认为顺序从最独特到最不独特。第二个问题是为什么ProfileName在索引中,而不是作为一个包含的列,而我们不是专门查询它?@Ianc:对于这个查询,它并不重要,因为搜索总是在整个元组
(ClientID,RegionID)
上执行。但是,如果需要单独搜索ClientID
(或与RegionID
以外的列组合搜索),则可以交换顺序ProfileName
在索引中,因为它在orderby
子句中使用。包含的列不按索引排序,因此如果将ProfileName
作为非键列包含,则查询需要排序。@谢谢。最后一个问题,如果你不介意的话。如果我需要经常搜索ClientID或RegionID,您提供的索引是否仍然是最佳的?@IanC:两个单独的索引最好:(ClientID,RegionID)
和RegionID
@Quassnoi我的朋友,您回来了。我猜你的意思是“…也保留主索引”?不仅仅是这一个索引?我有两个问题:1)我认为(ClientID,RegionID…)会更好,因为ClientID是最独特的列(好吧,我在我的问题中没有提到这一点,是的)。我认为顺序从最独特到最不独特。第二个问题是为什么ProfileName在索引中,而不是作为一个包含的列,而我们不是专门查询它?@Ianc:对于这个查询,它并不重要,因为搜索总是在整个元组(ClientID,RegionID)
上执行。但是,如果需要单独搜索ClientID
(或与RegionID
以外的列组合搜索),则可以交换顺序ProfileName
在索引中,因为它在orderby
子句中使用。包含的列不按索引排序,因此如果将ProfileName
作为非键列包含,则查询需要排序。@谢谢。最后一个问题,如果你不介意的话。如果我需要经常搜索ClientID或RegionID,您提供的索引是否仍然是最佳的?@IanC:两个单独的索引最好:(ClientID,RegionID)
和RegionID