sql-server – 标识列上的索引是否应该是非聚簇的?

对于具有标识列的表,是否应为标识列创建集群或非集群PK /唯一索引?

原因是将为查询创建其他索引.使用非聚簇索引(在堆上)并返回索引未涵盖的列的查询将使用较少的逻辑I / O(LIO),因为没有额外的聚簇索引b树搜索步骤?

create table T (
  Id int identity(1,1) primary key,-- clustered or non-clustered? (surrogate key,may be used to join another table)
  A .... -- A,B,C have mixed data type of int,date,varchar,float,money,....
  B ....
  C ....
  ....)

create index ix_A on T (A)
create index ix_..... -- Many indexes can be created for queries

-- Common query is query on A,C,....
select A,B 
from T 
where A between @a and @a+5 -- This query will have less LIO if the PK is non-clustered (seek)

select A,C
from T 
where B between @a and @a+5 

....

标识列上的聚类PK很好,因为:

>它单调增加,因此插入时不会分页.据说批量插入可以像堆(非聚集)表一样快
>它很窄

但是,如果不将其设置为群集,问题中的查询会更快吗?

**更新:**
如果Id是其他表的FK并且它将在某些查询中加入,该怎么办?

解决方法

认情况下,PK是聚集的,在大多数情况下,这很好.
但是,应该问哪个问题:

>我的PK应该聚集在一起吗?
>哪些列将是我的聚集索引的最佳密钥?

PK和Clustered索引是2个不同的东西:

> PK是一种约束. PK用于唯一标识行,但没有存储概念.但是,认情况下(在SSMS中),如果尚未存在聚簇索引,则由唯一聚簇索引强制执行.
>聚簇索引是一种特殊类型的索引,它在叶级别存储行数据,这意味着它始终覆盖.所有列,无论它们是否是密钥的一部分,都存储在叶级别.
它不必是唯一的,在这种情况下,将一个uniquifier(4个字节)添加到聚簇密钥.

现在我们最终得出两个问题:

>我如何唯一标识表格中的行(PK)
>我如何将其存储在索引的叶级(Clustered Index)

这取决于如何:

>您设计数据模型
>您查询数据并编写查询
>您插入或更新您的数据
> ……

首先,您需要聚集索引吗?如果批量插入,则将无序数据存储到HEAP(与群集中的有序数据相比)更有效.它使用RID(行标识符,8个字节)来唯一标识行并将其存储在页面上.

聚集索引不应该是随机值.
叶级别的数据将由索引键存储和排序.因此,它应该不断增长,以避免碎片或页面拆分.如果PK无法实现这一点,则应将另一个密钥视为群集候选.
由于所有行都将添加到最后一个叶子页面,因此从连续的角度来看,在identy列上的聚簇索引,顺序GUID甚至类似插入日期之类的东西都可以.
另一方面,尽管唯一标识符可能对您的业务需求有用,但它们不应该是群集的(它们是随机排序/生成的).

如果经过一些数据和查询分析,您发现在群集PK中进行密钥查找之前,您通常会使用相同的索引来获取数据,您可能会将其视为聚簇索引,尽管它可能无法唯一标识您的数据.

聚簇索引键由要索引的所有列组成.如果没有唯一约束,则添加uniquefier列(4个字节)(重复的增量值,否则为null).
然后,对于所有非聚簇索引的叶级别的每一行,将为此索引键存储一次.其中一些也将在索引树(B树)的根级别和叶级之间的中间级别(分支)存储多次.
如果密钥太大,所有非聚集索引将变大,将需要更多存储和更多IO,cpu,内存,…
如果您在名称出生日期国家/地区拥有PK,则此密钥很可能不是一个好的候选人.它对于聚簇索引来说太大了.使用NEWSEQUENTIALID()的Uniqueidentifier通常不被视为窄键(16字节),尽管它是顺序的.

然后,一旦弄清楚如何唯一地标识表中的行,就可以添加PK.如果您认为不在查询中使用它,请不要将其创建为群集.如果您有时需要查询它,仍然可以创建另一个非聚簇索引.请注意,PK将自动创建唯一索引.

非聚簇索引将始终包含聚簇键.但是,如果索引列(键列)覆盖,则聚簇索引中不会有任何键查找.
不要忘记您还可以在非聚集索引中添加Include和Where. (明智地使用它)

聚集索引应该是唯一的并且尽可能地窄
聚簇索引不应随时间变化,应逐步插入.

现在是时候编写一些sql来创建表,聚簇和非聚簇索引和约束.

这是理论上的,因为我们不知道您使用的数据模型和数据类型(A和B).

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...