非聚集如何影响聚集指数(PK)

时间:2016-02-16 05:56:01

标签: sql sql-server indexing query-optimization

Columns          | Data Type     | Allow Null
-----------------|---------------|-----------
Id (PK)          | int           | Unchecked
                 |               |  
Type             | tinyint       | Unchecked
                 |               |
Severity         | tinyint       | Unchecked
                 |               |
Message          | varchar(1000) | Unchecked
                 |               |
ReferenceTypeId  | int           | Checked
                 |               |
ReferenceId      | int           | Checked
                 |               |
ParentId         | int           | Checked
                 |               |
ParentTypeId     | int           | Checked
                 |               |
Created          | datetime      | Checked

好的,在上表中我有 10996674 记录。当我运行以下查询select count(id) from DTL_Event时,需要1:23分钟。

应用索引后

CREATE NONCLUSTERED INDEX DTL_Event_Optimization_Date on DTL_Event([Created])
CREATE NONCLUSTERED INDEX DTL_Event_Optimization_TypeIds_Composite on DTL_Event([ReferenceTypeId],[ParentTypeId])
CREATE NONCLUSTERED INDEX DTL_Event_Optimization_Reference_Parent_Ids_Composite on DTL_Event([ReferenceId],[ParentId])

相同的查询select count(id) from DTL_Event需要1秒。我需要知道为什么,因为Id是一个应该已经编入索引的主键,我在其他列上应用索引,这就是为什么我有一个问题:

  

为什么其他列上的NonClustered Indexing会优化此查询   select count(id) from DTL_Event。即为什么在其他列上应用非聚集索引有助于我更快地检索 Id的数量

2 个答案:

答案 0 :(得分:1)

一般来说,如果您的pk也是聚集索引,它也将存在于任何非聚集索引的叶级别。相反,所有表数据都存在于聚簇索引的叶级别。因此,如果您只是要求计数,那么您的一个非聚集索引可能会比聚簇更窄,并且可以满足查询,因此优化器将选择它。但是,如果添加where子句,则所有投注均已关闭。

答案 1 :(得分:1)

添加非聚簇索引后,QO正在选择非聚簇聚簇索引之一  只是因为这是最有效的方法,因为"页数"在索引中。

QO可能会选择(大部分时间)总体页数最低的非聚集索引。

您可能知道非聚簇索引在叶级别的其他索引/堆中具有唯一的查找标识符。

  

为什么其他列上的NonClustered Indexing会优化此查询   从DTL_Event中选择count(id)。即为什么申请Nonclustered   在其他列上建立索引有助于我更快地检索Id(s)的计数

在您的情况下,您是主要(群集和唯一)密钥ID,  所以每个非聚集都有叶级别的ID列  例如,您创建一个非聚集索引,如

>   CREATE NONCLUSTERED INDEX DTL_Event_Optimization_Date on
> DTL_Event([Created])

然后它会自动包含列ID

>   CREATE NONCLUSTERED INDEX DTL_Event_Optimization_Date on
> DTL_Event([Created]) 
> INCLUDE (ID)

所以实际上在添加非聚簇索引之后,查看rowcount的非聚簇索引非常有效,而不是查看聚簇索引,您可以在执行计划中查看相同的内容

TEST RIG:

CREATE Table DTL_Event (ID INT not null , TYPE tinyint not null  , Severity tinyint  not null ,[Message] varchar(1000) not null , ReferenceTypeId int ,ReferenceId int

 ,ParentId int , ParentTypeId int ,Created datetime   , primary key (ID))

没有非群组缩进

  select count(id) from DTL_Event

执行计划 enter image description here

WITH NONCLUSTERED INDEX

 CREATE NONCLUSTERED INDEX DTL_Event_Optimization_Date on DTL_Event([Created])



select count(id) from DTL_Event

执行计划 enter image description here

但如果您的目标是计算表中存在的总行数,那么最好的方法就是

SELECT SUM (row_count)
FROM sys.dm_db_partition_stats
WHERE object_id=OBJECT_ID('Transactions')   
AND (index_id=0 or index_id=1);