日期:2014-05-17  浏览次数:20475 次

对于MS [主键默认是聚集索引] 的质疑
1.ms sqlserver的默认特性:主键默认是聚集索引
2.我听到的一些与我的理解明显不同的言论:
  ..聚集索引所在的列或列的组合最好是唯一的
  ..最好使用自增列作为聚集索引列


上面这些我一直理解不能,而且持上述看法的不在少数,这与我的认知严重违背,有谁能有办法说服我,告诉我是我错了?


================================以下是我的看法================================

1.在大多数情况下我们的性能问题是读取而不是写入,客户反映我们的系统慢,通常说的是某个功能或报表的查询慢,而不是保存慢,即使对于一个写操作非常频繁的系统来说,读写的比例至少在10:1以上,普通的信息系统这个比例就更高了,所以"从性能的角度考虑"这句话,我认为是要重点考虑读取性能,而不是写入的性能。
基于上述原因,我认为我们在做设计的时候,如果能通过聚集显著的提升读取性能,那么我们就可以接受聚集带来的负面效果(写性能下降,以及表上其它非聚集索引的读性能下降)

2.聚集的优势在于读取批量且连续的记录,这是由聚集的物理形态决定的。比如读取一个月内的销售数据,如果按日期聚集,则这一个月内的数据所在的页面在物理上是连续的,可以极大避免最昂贵的磁头随机移动的操作,这是非聚集索引无法做到的。就好比你查字典,查找所有读音为 [ta] 的字效率很高,但是查找所有偏旁部首为 [亻]的字效率非常低。
因此基于上述分析:我认为聚集索引应该要选择一个离散度适中的列,以保证能够命中适当范围的记录,注意我的表述是[适当范围]:
如果命中范围太大则说明该列没有索引的价值(比如性别更,平均每次命中50%的记录)
如果命中范围太小则说明没有聚集的价值(比如主键,平均只能命中1条记录)

3.表上的聚集索引只能有一个,而且聚集还有负面影响,因此其宝贵程度不言而喻。而自长列通常在业务逻辑上毫无意义(用户不可能按自增长列来进行查询或分析等业务操作),这样的列用做主键没有问题,但用作聚集索引只能说是暴殄天物,原因与上面第2条同理:自增长列的离散度太低,导致选择性过高,每次只能命中一条记录,并不具备聚集的价值,这样的聚集还不如没有,因为我们承受了聚集带来的负面效果,却又没有体现出聚集的优势,因此我一向认为堆表的性能肯定要比那些设计得很糟糕的聚集表要高。

------解决方案--------------------
聚集索引所在的列或列的组合最好是唯一的
--> 不一定,当表的主键约束不是表的聚集索引时,聚集索引的列或列组合可以不是唯一的.

最好使用自增列作为聚集索引列
--> 不一定,但需看具体的情况.
个人不建议用自增列作主键或聚集索引,因为:
1.自增列的数据(1,2,3,4..)没有意义,纯属为了不重复而存在,占用存储空间(每行4kb).
2.浪费了对于一个表唯一的一个聚集索引,查询时的访问顺序:非聚集索引->聚集索引->数据页.
3.当重复写入相同的记录时,无法检查数据的唯一性,造成数据重复.
------解决方案--------------------
两位的精神这么好啊,都是半夜三更来提问回答问题的。
------解决方案--------------------
如果已经有适合业务主键的话可以不用逻辑主键,但我大部分时候都逻辑主键。首先自增列的写入性能好,其次占用空间小。使用复杂的业务主键的时候建立额外的索引是非常痛苦的事情。
create table (Country char(10),City char(20),Offcie char(50),Staff char(20),Primary key(Country,City,Office,Staff),Name varchar(50).......)
如果使用业务主键的话经常会看到这样的表,不考虑元数据,这个表主键占用的空间是100byte,假设有100W的数据的时候,要创建额外的索引需要使用索引列使用的空间+100byte*100W=100MB的空间。
create table (ID int identity(1,1) primary key,Country char(10),City char(20),Offcie char(50),Staff char(20,Name varchar(50).......)
使用这样的结构的话,最初使用的空间是更多的,首先需要4byte*100W=4MB的聚集索引的空间,其次还需要一个业务主键替代的非重复的索引100byte+4byte=104MB,但这个优势慢慢会体现在建立索引上,因为建立一个索引只需要额外的4MB的空间了,一般这样的表都会建立非常多的索引,因为检索条件是非常灵活的。

另一个问题是建立外键的时候,如果有100byte的业务主键,有100W的数据量,要还创建一个使用这个的外键表数据上亿的时候内心会有什么东西奔腾而过的。