表主键的作用在于确定记录的唯一性。许多人习惯性地认为数据库表必须有主键,于是纯粹的关联表都添加了主键,常见的关联表主键有GUID,iint,bigint。对这种表的操作和主键是没有关系的,通常是通过一个外键去操作多个外键,在插入之前还是要判断是否已经添加了重复列,当然可以通过对多个外键列添加唯一性约束,在这种情况下主键就更是多余了。
个人认为对这类表不需要添加主键。理由有:
1. 无主键的表不需要判断唯一性,插入的速度快。
2. 有主键的表会建立索引,索引文件也会占去很大的空间。
3. 数据的删除会涉及到索引的维护,因此会产生更大的日志文件。
对于大表,尽量使用文件组,如果可以使用分区就更好了(需要企业版)。在使用文件组时,同一个文件组的文件在同一个驱动器和在不同驱动器对性能都有所影响,总体性能而言是在不同的驱动器会好一些,不过差别不是很大。
下面是对一个流水表的测试,表的字段有5个int字段,一个datetime字段,一个real字段和一个guid字段,guid字段作为主键,该表是以时间顺序插入记录的。该表每条记录共48个字节,其中主键占去16个字节。对于SQLSERVER而言,主键将记录在索引文件中,因此两个表的数据库文件将相同,而索引文件部分就要多至少50%的储空间。
下面是对表插入2764800条记录,并选择其中的一部分数据,以及删除一天的数据的测试结果。SQLSERVER版本为SQLEXPRESS2005.
表类型 | 插入操作时间(秒) | 选择数据一 (仅WHERE字句)(秒) | 选择数据二 (SELECT DISTINCT)(秒) | 删除一天的数据 (WHERE语句)(秒) | 数据文件+ 索引文件(MB) | 日志文件(MB) |
有主键无文件组 | 3520 | 39.95 | 30.83 | 675.633 | 161 + 110 | 2124 |
有主键有文件组 | 2376 | 15.07 | 20.387 | 445 | 160 + 110 | 2124 |
无主键有文件组 | 1050 | 15.05 | 20.17 | 90 | 160 + 0.016 | 1198 |
由此可见,就这张流水表而言,有主键没有赋予它任何优势,相反的是,对于测试的各项指标均落后。另外使用文件组可以显著地提升数据库性能。