主键列上的非聚集索引?

use*_*158 8 sql-server indexing performance sql-server-2008

我在表上有一个主键(比如ContactID).SQL Server自动在此列上创建和维护聚簇INDEX.当我运行Tuning Advisor时(针对性能跟踪),它似乎建议在同一列上使用另一个INDEX - contactID列上的NON CLUSTERED索引.这将如何帮助 - 因为列上已经有聚簇索引?

Sul*_*lly 9

在非常特定的情况下,例如包含ContactID的表很大,和/或行很大(即大量的varchars),扫描聚簇索引可能是非常IO /内存密集型,而将ContactID作为聚簇索引和非聚集指数.

如果查询需要通过ContactID扫描表,并且ContactID上只有一个Clustered Index,则从磁盘读取整行数据.但是,如果在ContactID上也有非群集索引,则只从磁盘读取ContactID.

这与Clustered vs Non Clustered存储在磁盘上的方式有关.群集索引由ContactID存储,但所有行数据也与其一起存储.假设每行足够大以占用一页(8KB),那么扫描100,000,000行需要800,000,000 kb的磁盘io.

非聚集索引仅在其"行"中存储ContactID.假设ContactID是8个字节(bigint),那么1000个非聚集索引可以放在一个页面(8KB)中.现在,通过ContactID扫描100,000,000行只需要(100,000,000/1000*8)= 800,000 KB的磁盘io.

如果被分析的查询被相当频繁地调用,则800,000 KB与800,000,000 KB相比是重要的.

但是,正如Evadman建议的那样,Tuning Advisor只关注特定的工作负载.在大多数情况下,额外的非群集索引只是插入/删除的额外工作量.

现实生活中的例子,我使用了一个包含大量varchars的表.聚集索引是5521 MB.有几个查询,每秒调用很多次,最终会对Clustered Index列进行部分扫描(让我们称之为P_ID).P_ID上的非聚簇索引是211 MB(比聚集Idx小26倍).这导致查询执行时间以及磁盘和内存的负载大幅减少.

Bonus:查询以查找Clustered和Non Clustered索引的大小

DECLARE @TableName VARCHAR(200)
SET @TableName = 'NAME_OF_YOUR_TABLE'

SELECT
    OBJECT_NAME(i.OBJECT_ID) AS TableName,
    i.name AS IndexName,
    i.index_id AS IndexID,
    8 * SUM(a.used_pages) AS 'Indexsize(KB)',
    (8 * SUM(a.used_pages)) / 1024 AS 'Indexsize(MB)'
FROM sys.indexes AS i
JOIN sys.partitions AS p 
    ON p.OBJECT_ID = i.OBJECT_ID AND p.index_id = i.index_id
JOIN sys.allocation_units AS a 
    ON a.container_id = p.partition_id
WHERE OBJECT_NAME(i.object_id) = @TableName
GROUP BY i.OBJECT_ID,i.index_id,i.name
ORDER BY OBJECT_NAME(i.OBJECT_ID),i.index_id
Run Code Online (Sandbox Code Playgroud)


Eva*_*man 4

如果查询调优顾问建议在主键上使用非聚集索引,那么它也会建议在另一列(或多列)上使用聚集索引。

主键是约束,而不是索引。MS SQL Server 所做的假设是主键也是从表中检索数据的主要方式(通过“where ContactID = 2”或 ContactID 上的表之间的联接)。该假设意味着聚集索引也会在构成主键的列上自动创建。这种行为还有其他原因,但现在让我们保持简单。

现在,如果针对表的大多数查询都针对联系人名字(ContactFirstName 字段),如“Where ContactFirstName LIKE 'Muh%”,那么 SQL Server 将建议将聚集索引从 ContactID 更改为 ContactFirstName,因为表只能具有1 个聚集索引。主键约束仍然存在(并防止重复行),但表中的数据将按 ContactFirstName 进行物理排序。

调优顾问所消耗的工作负载将决定调优顾问的建议。调优顾问在做出决定时也将仅使用工作负载中最高资源查询的百分比,而不是整个工作负载。