Sql 聚集索引应该放在哪一列上?
最近,我一直在阅读各种类型的索引,主要的建议是将聚集索引放在表的主键上,但是如果主键实际上没有在查询中使用(通过选择或连接),而只是出于纯粹的关系目的而放置,那么在本例中它不会被查询。例如,假设我有一个Sql 聚集索引应该放在哪一列上?,sql,sql-server,database-design,indexing,Sql,Sql Server,Database Design,Indexing,最近,我一直在阅读各种类型的索引,主要的建议是将聚集索引放在表的主键上,但是如果主键实际上没有在查询中使用(通过选择或连接),而只是出于纯粹的关系目的而放置,那么在本例中它不会被查询。例如,假设我有一个car\u parts表,它包含3列,car\u part\u id,car\u part\u no,和car\u part\u titlecar\u part\u id是唯一的主键标识列。在这种情况下,car\u part\u no也是唯一的,很可能是car\u part\u titlecar\
car\u parts
表,它包含3列,car\u part\u id
,car\u part\u no
,和car\u part\u title
car\u part\u id
是唯一的主键标识列。在这种情况下,car\u part\u no
也是唯一的,很可能是car\u part\u title
car\u part\u no
是查询最多的对象,因此将聚集索引放在该列上而不是car\u part\u id
,难道没有意义吗?这个问题的基本问题是,哪一列实际上应该有聚集索引,因为您只被允许使用其中的一个?聚集索引应该放在查询最多的列上。这包括联接,因为联接必须像直接查询一样访问表,并找到指定的行
如果应用程序发生更改,并且您发现需要使用不同的索引结构优化表,那么您可以在以后重新生成索引
在MSDN上可以找到一些关于决定表的集群的附加指南:。记住使用模式;如果您几乎总是在car\u part\u no上查询数据库,那么将其聚集在该列上可能是有益的 但是,不要忘记连接;如果您经常加入表,并且加入使用car\u part\u id字段,那么您有充分的理由将集群保留在car\u part\u id上
要记住的另一件事(在本例中不是这样,但通常在考虑聚集索引时)是聚集索引将隐式地出现在表上的每个其他索引中;例如,如果要为car\u part\u title编制索引,该索引还将隐式包含car\u part\u id。这会影响索引是否覆盖查询,也会影响索引将占用多少磁盘空间(这会影响内存使用等)。查询数据范围时,聚集索引很好。比如说
SELECT * FROM theTable WHERE age BETWEEN 10 AND 20
聚集索引在计算机磁盘上按特定顺序排列行。这就是为什么年龄=10的行彼此相邻,然后是年龄=11的行,以此类推
如果您有“精确选择”,请如下所示:
SELECT * FROM theTable WHERE age = 20
非聚集索引也很好。它不会重新排列计算机磁盘上的数据,但会构建一个特殊的树,其中包含指向所需行的指针
因此,它在很大程度上取决于您执行的查询类型。当且仅当索引中最左边的键被过滤时,查询优化器才可以使用聚集索引或非聚集索引。因此,如果在列(A、B、C)上定义索引,则
B=@B
、onC=@C
或onB=@B和C=@C
上的WHERE条件将无法充分利用索引(请参见注释)。这也适用于联接条件。凡包含<代码> A/<代码>的任何过滤器都将考虑索引:<代码> A>=A<代码>或<代码> A= @ A和B= @ B<代码>或>代码> A= @ A和C=@ C < /代码>或<代码> A= @ A和B=@ B和C=@ C < /代码> .
因此,在您的示例中,如果将part\u no
上的聚集索引作为最左边的键,则查找特定part\u id
的查询将不会使用该索引,并且part id
上必须存在单独的非聚集索引
现在我们来讨论一下,在众多索引中,哪些应该是聚集索引。如果您有几个重要性和频率大致相同的查询模式,并且在所需的键方面相互矛盾(例如,part\u no
或part\u id
的频繁查询),那么您需要考虑其他因素:
- 宽度:聚集索引键被所有其他非聚集索引用作查找键。因此,如果您选择一个宽键(比如两个未限定的列),那么您将使所有其他索引变宽,从而消耗更多的空间,生成更多的IO,并降低所有操作的速度。因此,从读取的角度来看,在同等好的键之间,选择最窄的一个作为聚集键,并将较宽的键设置为非聚集键
- 争用:如果您有特定的插入和删除模式,请尝试将它们物理地分开,以便它们出现在聚集索引的不同部分。例如,如果表充当一个队列,所有插入在一个逻辑端,所有删除在另一个逻辑端,请尝试布局聚集索引,以便物理顺序与此逻辑顺序匹配(例如排队顺序)
- 分区:如果表非常大,并且您计划部署分区,那么分区键必须是聚集索引。典型的例子是使用滑动窗口分区方案归档的历史数据。即使实体有一个逻辑主键,比如“entity_id”,集群索引也是由一个datetime列完成的,该列也用于分区函数
- 稳定性:经常更改的键对于聚集键来说不是很好的候选键,因为每个键都会更新聚集键值,并强制所有非聚集索引更新它们存储的查找键。由于更新聚集键也可能会将记录重新定位到不同的页面,因此可能会导致聚集索引上出现碎片
B=@B
上有一个WHERE filter,并且查询项目C
,则该索引很可能会被使用,但不会用作搜索或扫描,因为它仍然是fas