如果集群索引不唯一会发生什么?插入的行是否会流向某些“溢出”页面,从而导致性能下降?
它是否可以“强制”唯一化?最好的方法是什么?
我之所以提问,是因为我目前正在使用聚集索引来将我的表划分为逻辑部分,但性能一般,最近我得到了建议将我的聚集索引设置为唯一。我想听听第二个意见。
如果集群索引不唯一会发生什么?插入的行是否会流向某些“溢出”页面,从而导致性能下降?
它是否可以“强制”唯一化?最好的方法是什么?
我之所以提问,是因为我目前正在使用聚集索引来将我的表划分为逻辑部分,但性能一般,最近我得到了建议将我的聚集索引设置为唯一。我想听听第二个意见。
它们不一定要是唯一的,但鼓励使用唯一值。
到目前为止,我还没有遇到过想在非唯一列上创建CI的情况。
如果聚集索引不是唯一索引,SQL Server将通过添加称为唯一化器的内部生成值来使任何重复键唯一。
这会导致性能下降吗?
添加唯一化器肯定会增加计算和存储的开销。
这种开销是否会明显取决于几个因素:
编辑
评论中Remus指出,确实存在创建非唯一CI的用例。我还没有遇到过这些场景只是显示了我自己的暴露度或能力不足(选择自己喜欢的)。
我喜欢看看索引女王金伯利·特里普在这个话题上有什么说法:
我要从聚集键的推荐开始,原因有几个。首先,这是一个容易做出的决定,其次,早期做出这个决定有助于主动预防某些类型的碎片化。如果您能预防某些基表碎片化类型,那么您可以最小化一些维护活动(其中一些在SQL Server 2000中,以及在SQL Server 2005中较少)需要将表离线。好的,我稍后会谈到重建的内容.....
让我们从我在聚集键中寻找的关键要素开始:
* Unique
* Narrow
* Static
newsequentialid()
来获得几乎按顺序排列的GUID。但是,如果你添加自己的唯一ID(我总是喜欢INT IDENTITY),然后你就可以使用它(例如建立一个FK关系)。SQL Server添加的唯一标识符对你来说是不可见的,因此它们只是你无法利用的开销。 - marc_sSELECT * FROM EmployeeTable WHERE DepartmentId=%DepartmentValue%
DepartmentId
不是唯一索引,那么最好将其作为聚集索引来提高性能(尤其是因为这样可以确保给定的DepartmentId
内的所有记录都被聚集)。例如,Clustered Index Design Guidelines中就指出:
例如,如果大多数查询都想选择给定城镇内的记录,则选择“Country”作为聚集索引并不好。除了少数例外情况外,每个表都应该定义一个聚集索引,该索引基于以下列或列组:
- 可用于频繁使用的查询。
- 提供高度的唯一性。
- 可用于范围查询。
如果您正在调整旧数据库,则这是一个及时雨。我正在解决20年历史的数据库性能问题。它有具有3到8个列的非聚集主键。我可以选择一个具有广泛分布的列,而不是使用所有8个列来确保唯一性,并且应用了Uniqueifier。它是一个Int,但是通过使用像项目ID这样的列,它可以处理2147483647个唯一的项目ID,足以满足大多数用例。如果不够,请将第二或第三列添加到群集中。这可以在应用程序层不进行任何编码修改的情况下完成。20年的生产和管理不必要求进行重大重写。