将主键聚集索引替换为另一个索引会导致问题吗?

时间:2014-01-30 13:20:05

标签: sql sql-server join indexing

使用SQL Server 2008/2012,我目前有两个表,如下所示:

tblAccount (accountID BIGINT, accountActive BIT)

tblSite (siteID BIGINT, accountID BIGINT, siteActive BIT)

目前,accountID上的tblAccount是主键和聚集索引。

siteID上的tblSite是主键和聚集索引

我的大部分查询都采用以下形式:

SELECT <fields>
FROM <some table> X
INNER JOIN tblSite s ON s.siteID = X.siteID
INNER JOIN tblAccount a ON a.accountID = s.accountID
WHERE 
   x.<field> = SOMETHING  
   AND a.accountActive = 1 
   AND s.siteActive = 1

我的理解是,为了优化这些查询,最好将新的聚簇索引放在tblAccounttblSite上。

类似的东西:

CREATE CLUSTERED INDEX ON tblAccount (accountActive,accountID) WITH .....

CREATE CLUSTERED INDEX ON tblSite (siteActive,siteID) WITH .....

显然,要做到这一点,我必须删除两个表的PK聚簇索引。

这是否有可能导致问题进一步发生?正如我假设(采用帐户表),该表现在已针对

进行了优化
SELECT * 
FROM tblAccount 
WHERE accountID = X 
  AND accountActive = Y

所以只做

SELECT * 
FROM tblAccount 
WHERE accountID = X

将是高度未经优化的吗?

我在帐户表上创建了另外两个索引,我不知道这些索引会对上述索引产生多大影响。查询:

CREATE UNIQUE NONCLUSTERED INDEX idx_account_session 
    ON tblAccount (accountSessionKey,accountActive,accountAffirmed,accountLastAction)     
    INCLUDE (accountID) 
    WITH (STATISTICS_NORECOMPUTE=OFF,SORT_IN_TEMPDB=ON,FILLFACTOR=80)

CREATE NONCLUSTERED INDEX idx_account_login 
    ON tblAccount (accountEmail,accountPassword,accountAffirmed,accountActive) 
    INCLUDE (accountID,accountSaltHash) 
    WITH (STATISTICS_NORECOMPUTE=OFF,SORT_IN_TEMPDB=ON,FILLFACTOR=80)

我已经将这些用于优化身份验证存储过程。

非常感谢你的帮助。

1 个答案:

答案 0 :(得分:1)

更改聚簇索引将改变表的工作方式,当前accountID是唯一的,但如果您在accountID和Active上创建聚簇索引,则最终可能会有2条记录用于同一帐户ID(一个活动,一个不)。因此,为了更改聚类键并保持AccountID唯一,您还需要添加唯一约束(或唯一索引)。

如果您将在大多数时间查询活动帐户/网站,并且您认为性能有问题,我会选择indexed view,并将您的聚集索引保持在accountID上。< / p>

CREATE VIEW dbo.ActiveAccount
WITH SCHEMABINDING
AS
    SELECT  AccountID, <Columns>
    FROM    dbo.tblAccount 
    WHERE   ActiveAccount = 1;
GO
CREATE UNIQUE CLUSTERED INDEX UQ_ActiveAccount_AccountID 
    ON dbo.ActiveAccount (AccountID);
GO

还有类似的Site索引视图,因此您的查询变为:

SELECT  <columns>
FROM    ActiveAccount A (NOEXPAND)
        INNER JOIN ActiveSite s (NOEXPAND)
            ON a.accountID = s.accountID;

但是当您希望所有帐户/网站不仅仅是活动帐户/网站时,您可以查询主表而不是索引视图。

请注意,维护此索引视图的成本可能超过您从中获取的好处,如评论中所述,它取决于数据的基数,以及您只需要查询活动帐户/网站。