关于数据库设计中主键问题的思考
数据库的主键与外键设计原则与解析

数据库的主键与外键设计原则与解析数据库的主键(Primary Key)和外键(Foreign Key)在设计和构建数据库时起着至关重要的作用。
它们不仅能够保证数据的完整性和一致性,还能够提高数据库的性能和查询效率。
本文将深入探讨数据库的主键和外键设计原则,解析其重要性和应用场景。
首先,我们来了解主键的概念和设计原则。
主键是用来唯一标识数据库表中的每一行数据的一列或一组列。
主键必须满足以下条件:唯一性、非空性和不可变性。
唯一性保证了每一行数据都有一个唯一的标识符,这样就可以通过主键值来准确定位和访问特定的数据。
非空性要求主键的值不能为NULL,确保每一行数据都有一个有效的主键值。
不可变性意味着主键的值在行的生命周期内保持不变,不允许对主键进行修改。
在设计主键时,通常有两种选择:自然主键和人工主键。
自然主键是从表中已有的某些列中选择一个作为主键,例如学生表中的学号、订单表中的订单号等。
自然主键有一个明显的优点,即具有含义,能够直观地表示表中的某些属性。
然而,自然主键的缺点是容易发生冲突和变化,例如学生调整学号或订单被撤销后再次生成订单号等。
为了解决这些问题,人工主键即是通过增加一个特定的列来作为主键,例如自增列或全局唯一标识符(GUID)。
人工主键的优点是稳定和唯一,不容易发生变化和冲突,但缺点是相对于自然主键而言会增加额外的存储和维护成本。
接下来,我们探讨外键的概念和设计原则。
外键是用来建立数据表之间的关联关系的一列或一组列,它引用了另一个表中的主键。
外键能够保证数据的一致性和完整性,并且确保相关表之间的关联关系正确有效。
外键还可以用于实现表之间的连接和查询操作,提高查询效率和性能。
在设计外键时,需遵循以下原则。
首先,外键的值必须与所引用主键的值保持一致,确保所建立的关联关系是正确有效的。
其次,外键的值可以为空,表示当前行的数据未与其他表建立关联。
第三,外键的删除和更新操作应该受到限制,以免破坏关联关系和数据的一致性。
数据库主键设计的原则与方法

数据库主键设计的原则与方法在数据库设计过程中,主键的设计是至关重要的一步。
主键的选择会影响数据库的性能和数据完整性。
因此,本文将介绍数据库主键设计的原则与方法,以帮助读者更好地理解和应用主键设计。
1. 原则一:唯一性主键必须具有唯一性,即每条记录的主键值必须是唯一的。
这样可以确保数据库中不存在重复的数据,避免数据冗余和不一致性。
常用的实现唯一性的方法包括自增长字段、全局唯一标识符(GUID)等。
2. 原则二:稳定性主键的值应该是稳定的,不会频繁发生变化。
主键的变化会引起相关数据的变动,增加数据库维护的复杂度和成本。
因此,最好选择一个与业务逻辑无关、不会经常改变的属性作为主键。
3. 原则三:简洁性主键的设计应该简洁明了,避免过于复杂的组合字段作为主键。
复杂的主键设计会增加数据库的存储空间和查询的复杂度,影响数据库的性能。
通常情况下,使用一个字段作为主键已经足够满足大部分需求。
4. 原则四:不可空性主键的值不应该为空,它应该在插入新记录时必须有值。
空主键将导致数据库无法保证记录的唯一性和一致性。
如果数据库中某些记录没有主键值,可以考虑使用自增长字段或者默认值作为主键。
5. 方法一:自增长主键自增长主键是最常用的主键设计方法之一。
数据库会自动为每条新插入的记录分配一个唯一的主键值,无需手动指定。
这种主键设计简单方便,且能够确保唯一性。
6. 方法二:组合主键在某些情况下,使用一个字段作为主键可能无法满足需求。
可以考虑使用多个字段组合作为主键,称之为组合主键。
组合主键要求多个字段的组合值在整个表中唯一。
7. 方法三:全局唯一标识符(GUID)全局唯一标识符(GUID)是一个128位的二进制数,通常以字符形式呈现。
GUID保证在全球范围内的唯一性,适用于分布式系统。
可以将GUID作为主键,确保数据在不同数据库之间的唯一性。
8. 方法四:业务相关字段在某些情况下,可以使用业务相关字段作为主键。
例如,对于一个学校的学生表,可以使用学生的学号作为主键。
主键的作用

数据库主键设计之思考主键的必要性:有些朋友可能不提倡数据库表必须要主键,但在我的思考中,觉得每个表都应该具有主键,不管是单主键还是双主键,主键的存在就代表着表结构的完整性,表的记录必须得有唯一区分的字段,主键主要是用于其他表的外键关联,本记录的修改与删除,当我们没有主键时,这些操作会变的非常麻烦。
主键的无意义性:我强调主键不应该具有实际的意义,这可能对于一些朋友来说不太认同,比如订单表吧,会有“订单编号”字段,而这个字段呢在业务实际中本身就是应该具有唯一性,具有唯一标识记录的功能,但我是不推荐采用订单编号字段作为主键的,因为具有实际意义的字段,具有“意义更改”的可能性,比如订单编号在刚开始的时候我们一切顺利,后来客户说“订单可以作废,并重新生成订单,而且订单号要保持原订单号一致”,这样原来的主键就面临危险了。
因此,具有唯一性的实际字段也代表可以作为主键。
因此,我推荐是新设一个字段专门用为主键,此主键本身在业务逻辑上不体现,不具有实际意义。
而这种主键在一定程序增加了复杂度,所以要视实际系统的规模大小而定,对于小项目,以后扩展不会很大的话,也查允许用实际唯一的字段作主键的。
主键的选择我们现在在思考一下,应该采用什么来作表的主键比较合理,申明一下,主键的设计没有一个定论,各人有各人的方法,哪怕同一个,在不同的项目中,也会采用不同的主键设计原则。
第一:编号作主键此方法就是采用实际业务中的唯一字段的“编号”作为主键设计,这在小型的项目中是推荐这样做的,因为这可以使项目比较简单化,但在使用中却可能带来一些麻烦,比如要进行“编号修改”时,可能要涉及到很多相关联的其他表,就象黎叔说的“后果很严重”;还有就是上面提到的“业务要求允许编号重复时”,我们再那么先知,都无法知道业务将会修改成什么?第二:自动编号主键这种方法也是很多朋友在使用的,就是新建一个ID字段,自动增长,非常方便也满足主键的原则,优点是:数据库自动编号,速度快,而且是增量增长,聚集型主键按顺序存放,对于检索非常有利;数字型的,占用空间小,易排序,在程序中传递也方便;如果通过非系统增加记录(比如手动录入,或是用其他工具直接在表里插入新记录,或老系统数据导入)时,非常方便,不用担心主键重复问题。
数据库设计中主键与外键的最佳实践方法

数据库设计中主键与外键的最佳实践方法在数据库设计中,主键和外键是关系型数据库中非常重要的概念,它们的正确使用对于数据库的性能和数据完整性具有关键影响。
本文将介绍主键和外键的最佳实践方法,帮助你在数据库设计中做出正确的决策。
首先,让我们明确主键和外键的概念。
主键是用于唯一标识数据库表中每一行数据的列或一组列。
通过唯一标识,主键确保了数据的完整性和一致性。
常用的主键类型包括自增长整数、GUID(全局唯一标识符)和业务相关的自然键。
外键是指两个数据库表之间的关联关系,它基于某个表的主键而在另一个表中建立的关联。
外键确保了相关数据之间的引用完整性,可以简化协作操作和数据查询。
接下来,我们来讨论主键的最佳实践方法。
以下是一些需要考虑的方面:1.选择适当的主键类型:主键的类型应根据具体情况来选择。
自增长整数是一个常用的选择,可以确保唯一性,并且具有良好的性能。
GUID主键虽然可以在分布式环境中确保唯一性,但占用更大的存储空间和索引空间,并且查询性能较差。
业务相关的自然键可以更好地反映数据的语义。
2.避免过长的主键:主键的长度应尽可能地保持较小,以减少存储空间和索引空间的占用。
过长的主键可能会导致性能下降,并且在外键关联时会增加复杂性。
3.使用对查询友好的主键:在一些需要频繁查询的表中,使用能够加快查询速度的主键可以提高数据库性能。
例如,在需要按时间范围查询的表中,使用以时间为前缀的自增长整数作为主键可以更快地定位数据。
然后,来看看外键的最佳实践方法:1.确保外键的引用完整性:外键可以确保表之间的数据关联完整性,因此在设计数据库时应该合理地定义和使用外键。
通过定义外键关系,可以防止无效的引用,避免数据的不一致。
2.注意外键的级联更新和级联删除:在定义外键关系时,需要考虑级联更新和级联删除的行为。
级联更新会自动更新与外键关联的表中的相关数据,而级联删除会自动删除与外键关联的表中的相关数据。
在使用级联操作之前,一定要仔细考虑可能产生的副作用。
MySQL中的主键和索引设计经验分享

MySQL中的主键和索引设计经验分享引言在数据库设计和优化中,主键和索引是两个至关重要的概念。
它们的正确使用和优化对于提高查询效率和保证数据完整性都起着重要的作用。
本文将分享在MySQL中主键和索引设计的一些经验和技巧,希望能对读者在数据库设计和优化方面提供一些帮助和启发。
一、主键的作用和选择1. 主键的作用主键是唯一标识一条记录的字段,它能够确保每一条记录都有唯一的标识符。
主键的作用有以下几个方面:- 保证数据完整性:主键的唯一性能够确保每一条记录都有独一无二的标识符,避免数据冗余和错误。
- 提高查询效率:主键作为表中的唯一标识,MySQL会自动为主键创建索引,通过索引可以快速定位和访问记录。
- 支持关联和连接:主键可以用于关联表之间的关系,比如外键引用。
通过主键和外键的关系,可以建立表与表之间的连接。
2. 主键的选择选择合适的主键是数据库设计的关键一步。
一般来说,满足以下条件的字段可以作为主键:- 唯一性:主键的值必须唯一,不能重复。
- 稳定性:主键的值应该是相对稳定不变的,不能频繁变动。
- 简洁性:主键的值应该尽可能简洁,避免过长的主键对于存储和查询的性能造成影响。
- 可读性:主键的值应该容易理解和识别,方便人们对数据进行管理和查询。
根据具体业务需求和数据特点,可以选择一个或多个字段作为主键。
常见的选择包择有:- 自增ID:使用自增长的整数作为主键,可以保证唯一性和简洁性,也方便数据库的管理。
- UUID:使用全球唯一标识符作为主键,可以保证唯一性,但会增加存储和查询的复杂度。
- 组合主键:使用多个字段组合而成的主键,可以更加灵活地满足业务需求,但会增加复杂性。
二、索引的作用和设计1. 索引的作用索引是数据库中用于提高查询效率的重要工具,它能够加快数据的定位和访问。
索引的作用主要有以下几个方面:- 提高查询效率:通过在索引字段上建立索引,可以加快数据的查找速度,减少数据库的查询时间。
- 优化排序和分组:索引可以加快排序和分组操作的速度,提高数据库的整体性能。
数据库设计中的主键和外键使用准则(六)

数据库设计中的主键和外键使用准则在数据库设计中,主键和外键是两个重要的概念。
主键用来唯一标识数据库表中的每一条记录,而外键则用来建立表与表之间的关联关系。
在实际的数据库设计过程中,正确地使用主键和外键是至关重要的,可以确保数据库的数据完整性和一致性。
本文将探讨数据库设计中主键和外键的使用准则。
1. 主键的选择主键是用来唯一标识数据库表中每一条记录的字段或字段组合。
在选择主键时,需要考虑以下几个准则:唯一性主键必须具有唯一性,即每个记录的主键值都不相同。
这可以通过设置数据库表的主键约束来实现。
稳定性主键的值应该是稳定的,即不会随着时间的推移而发生改变。
这样可以确保主键的唯一性和数据的一致性。
简洁性主键的值应该尽可能简洁,以便提高数据库的查询和操作效率。
一般来说,可以选择整型数据类型作为主键。
可读性主键的值应该具有一定的可读性,以便人工识别和操作数据。
可以考虑使用自增长的方式为主键赋予更直观的含义。
2. 外键的使用外键用来建立表与表之间的关联关系,可以确保数据之间的一致性和完整性。
在使用外键时,需要考虑以下几个准则:引用完整性外键应该引用到一个已经存在的表中的主键。
这样可以确保数据的引用关系的完整性,防止数据的孤立或者冗余。
级联操作在建立外键关系时,可以选择级联操作,在主表或者外键表上进行的修改、删除操作会自动引发相关的级联操作,保证数据的一致性。
索引性能外键字段的索引可以提高查询的性能。
在设计数据库时,可以选择在外键字段上建立索引,以提高数据操作的效率。
规范命名外键字段应该有一个规范的命名,可以直观地表达它与主表之间的关系。
命名规范可以有助于更清晰地理解和维护数据库结构。
3. 主键和外键的适用场景主键和外键的使用并不是适用于所有的场景。
在确定是否使用主键和外键时,需要综合考虑以下几个因素:数据关联性如果数据库中的表之间存在较为复杂的关联关系,如一对多、多对多等情况,那么使用外键可以方便地维护数据的一致性和完整性。
MySQL数据库设计中的主键和唯一键使用

MySQL数据库设计中的主键和唯一键使用在数据库设计中,主键(Primary Key)和唯一键(Unique Key)是非常重要的概念,它们的正确使用和合理设计对于数据库的性能和数据的完整性都起着至关重要的作用。
本文将针对MySQL数据库中的主键和唯一键进行深入的讨论和分析。
一、主键的定义和作用主键是用来唯一标识一条记录的字段或字段组合,它具有以下特点和作用:1. 唯一性:主键的值在整个表中必须是唯一的,每个记录必须具有唯一的主键值,否则会违反主键的定义。
2. 非空性:主键的值不能为空,因为为空的记录无法唯一标识。
3. 确定性:通过主键可以确定一条记录,即通过主键值可以唯一地定位一条记录。
4. 数据索引:主键字段会默认创建索引,加速数据检索和查询的效率。
在MySQL数据库中,常见的主键类型有:1. 单字段主键:以表中的某个字段作为主键,例如用户表中的id字段。
2. 复合主键:以多个字段的组合作为主键,例如订单表中的orderId和userId 字段的组合。
3. 自增主键:自动增长的主键值,通常用于单字段主键的设计,例如id字段。
二、主键的设计原则和注意事项在设计和选择主键时,需要遵循以下原则和注意事项:1. 简洁性:主键应该尽可能简洁、明确,不要选择过长或者复杂的字段作为主键,以免增加数据库的负担和降低查询性能。
2. 不可变性:主键的值在记录创建后应该是不可变的,不应该频繁修改主键的值,否则容易引发数据库冲突和数据一致性问题。
3. 避免业务含义:主键并不一定要有业务含义,最好不要使用带有业务含义的字段作为主键,尽量使用无意义的自增主键或者全局唯一标识符(GUID)。
4. 合理选择主键类型:根据需要选择适当的主键类型,如果需要保证全局唯一性,可以选择GUID作为主键类型,如果只是保证表内唯一性,可以选择自增主键或者复合主键。
5. 性能考虑:主键字段会默认创建索引,在设计主键时要考虑索引对查询性能的影响,尽量选择较小的数据类型来减少索引的大小和提高查询效率。
数据库主键设计最佳实践与技巧分享

数据库主键设计最佳实践与技巧分享随着数据量的增加和数据存储的重要性日益提升,在设计数据库时,主键的选择和设计变得越来越重要。
数据库主键的设计不仅影响了数据的完整性和一致性,还直接影响了数据库的性能。
在本篇文章中,我将分享一些数据库主键设计的最佳实践和技巧,希望能给读者提供有关数据库主键设计方面的价值和启示。
首先,让我们明确什么是主键。
主键是数据库表中的一个字段或一组字段的唯一标识符。
主键的作用是确保表中的每一行数据都是唯一的,并且能够准确且快速地找到指定的记录。
在设计数据库主键时,以下是些最佳实践和技巧可以参考:1. 使用自增整数作为主键:将整数设置为主键是一种常见的选择。
自增整数具有较小的存储空间、快速的查找速度和简化的索引设计等优点。
通过自动增长的方式创建主键,可以确保主键的唯一性,同时避免了手动指定主键的复杂性和错误。
2. 避免使用具有业务含义的字段作为主键:尽量避免使用具有业务含义的字段作为主键,因为业务逻辑可能会发生变化,导致主键的复杂度增加。
例如,使用电子邮件地址作为主键可能会导致未来无法更改用户的邮箱地址。
相反,使用生成的标识符或唯一代码作为主键,可以更好地适应业务需求的变化。
3. 考虑多列主键:有时候,单个字段无法唯一标识一行数据。
在这种情况下,可以考虑使用多个字段组成复合主键。
例如,在一个订单表中,订单编号和产品ID组成的复合主键可能更适合确保唯一性和数据完整性。
4. 使用UUID作为主键的替代方案:如果需要在分布式环境下使用主键,传统的自增整数可能无法满足需求。
UUID(全局唯一标识符)是一种基于标准的方法,可以在多个节点之间生成唯一标识符。
使用UUID作为主键可以确保在整个分布式系统中的唯一性,但可能会牺牲一些性能。
5. 考虑主键索引的性能:主键是数据库表的主要索引,对数据库的性能影响很大。
因此,在设计主键时,应该考虑将其设置为聚集索引(clustered index),以提高数据库的查询性能。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
关于数据库设计中主键问题的思考文章摘要:数据库主键在数据库中占有重要地位。
主键的选取策略决定了系统是否可靠、易用、高效。
本文探讨了数据库设计过程当中常见的主键选取策略,并剖析了其做主键的优缺点,提出了相应的解决问题的方法。
关键字:自增标识GUID COMB在基于关系型数据库设计时候,通常要为每张表指定一个主键,所谓主键就是能够唯一标识表中某一行记录的属性或属性组,一个表只能有一个主键,但可以有多个候选索引。
因为主键可以唯一标识某一行记录,所以可以确保执行数据更新、删除、修改时不出现错误。
当然,其它字段可以辅助我们在执行这些操作时消除共享冲突,不是本文讨论的重点,不再赘述。
主键除了上述作用外,常常与外键构成参照完整性约束,防止出现数据不一致。
所以数据库在设计时,主键起到了很重要的作用。
常见的数据库主键选取方式有:自动增长式、手动增长式、UniqueIdentifier、联合式(复合式)、时间序列+随机数式、“COMB(Combine)”类型。
一、自动增长式很多数据库设计者喜欢使用自动增长型字段,因为它使用简单。
自动增长式允许我们在向数据库添加数据时,不考虑主键的取值,记录插入后,数据库系统会自动为其分配一个值,确保绝对不会出现重复。
如果使用SQL Server数据库的话,我们还可以在记录插入后使用@@IDENTITY全局变量获取系统分配的主键值。
尽管自动增长式字段会省掉我们很多繁琐的工作,但使用它也存在潜在的问题,那就是在数据缓冲模式下,很难预先填写主键与外键的值。
假设有主辅两张表:Order(OrderID, OrderDate) 订单表OrderDetial(OrderID, LineNum, ProductID, Price) 订单明细表Order 表中的OrderID是自动增长型的字段。
假设现在需要我们录入一张订单,包括在Order表中插入一条记录以及在OrderDetail表中插入若干条记录。
因为Order表中的OrderID是自动增长型的字段,那么我们在记录正式插入到数据库之前无法事先得知它的取值,只有在更新后才能知道数据库为它分配的是什么值。
这会造成以下矛盾发生:首先,为了能在OrderDetail的OrderID字段中添入正确的值,必须先更新Order表以获取到系统为其分配的OrderID值,然后再用这个OrderID填充OrderDetail表的OrderID列。
最后更新OderDetail表。
但是,为了确保数据的一致性,Order与OrderDetail在更新时必须在事务模式下进行的,即要么两张表同时同时更新成功、要么全部失败,显然它们是相互矛盾的。
其次,当我们需要在多个数据库间进行数据的复制时(SQL Server的数据分发、订阅机制允许我们进行库间的数据复制操作),自动增长式字段可能造成数据合并时的主键冲突及表关联关系的丢失。
设想一个数据库中的Order表向另一个库中的Order表复制数据库时,OrderID到底该不该自动增长呢?如果自动增长,其子表OrderDetial的关联关系会丢失,如果不增长就会和现有数据主键重复,是不是很矛盾呢?再次,自增量的值都是需要在系统中维护一个全局的数据值,每次插入数据时即对此次值进行增量取值。
当在产生唯一标识的并发环境中,每次的增量取值都必须为此全局值加锁解锁以保证增量的唯一性。
造成并发瓶颈,降低查询性能。
还有当数据表足够大或频繁的更改和插入操作导致主键类型值超出范围,这种情况一般很少碰到,但也是我们进行数据表设计时必须考虑的一个问题二、手动增长型字段既然自动增长型字段会带来如此的麻烦,我们不妨考虑使用手动增长型的字段,也就是说主键的值需要自己维护,通常情况下需要建立一张单独的表存储当前主键键值。
为了叙述上的方便仍然利用上面的例子进行阐述,新建一张表叫IntKey,包含两个字段,KeyName以及KeyValue。
就像一个HashTable,给一个KeyName,就可以知道目前的KeyValue是什么,然后手工实现键值数据递增。
在SQL Server中可以编写这样一个存储过程,让取键值的过程自动进行。
代码如下:CREATE PROCEDURE [GetKey]@KeyName char(10),@KeyValue int OUTPUTASUPDATE IntKey SET @KeyValue = KeyValue = KeyValue + 1 WHERE KeyName = @KeyNameGO这样,通过调用存储过程,我们可以获得最新键值,确保不会出现重复。
若将OrderID字段设置为手动增长式字段,我们的程序可以由以下几步来实现:首先调用存储过程,获得一个OrderID,然后使用这个OrderID填充Order表与OrderDetail表,最后在事务机制下对两表进行更新。
使用手动增长式字段作为主键在进行数据库间数据复制时,可以确保数据合并过程中不会出现键值冲突,只要为不同的数据表分配不同的主键取值段就行了。
但是,使用手动增长型字段会增加网络的负担,必须通过增加一次数据库访问来获取当前主键键值,这会增加网络和数据库的负载,当处于一个低速或断开的网络环境中时,这种做法会有很大的弊端。
同时,手工维护主键还要考虑并发冲突等种种因素,这更会增加系统的复杂程度。
三、使用UniqueIdentifierSQL Server为我们提供了UniqueIdentifier数据类型,并提供了一个生成函数NEWID( ),使用NEWID( )可以生成一个唯一的UniqueIdentifier。
UniqueIdentifier在数据库中占用16个字节,出现重复的概率几乎为0,号称全球唯一标识。
我们经常从注册表或WINDOWS程序出现错误需要调试时看到类似768427bf-9b37-4776-97ca-000365e160d5或{45F0EB02-0727-4F2E-AAB5-E8AEDEE0CEC5} 的东西实际上就是一个UniqueIdentifier,Windows用它来做COM组件以及接口的标识,防止出现重复。
在.NET中UniqueIdentifier称之为GUID(Global Unique Identifier)。
在C#中可以使用如下命令生成一个GUID:Guid u = System.Guid.NewGuid();对于上面提到的Order与OrderDetail的程序,如果选用UniqueIdentifier作为主键的话,我们完全可以避免上面提到的增加网络RoundTrip的问题。
通过程序直接生成GUID填充主键,不用考虑是否会出现重复。
但是UniqueIdentifier 字段也存在严重的缺陷:首先,它的长度是16字节,是整数的4倍长,会占用大量存储空间。
更为严重的是,UniqueIdentifier的生成毫无规律可言,也就是说是无序的,要想在上面建立索引(绝大多数数据库在主键上都有索引)是一个非常耗时的操作。
有人做过实验,当数据表记录比较大的时,在不同的数据量级别上插入同样的数据量,使用UniqueIdentifier型数据做主键要比使用Integer型数据慢,且还没有考虑到表关联的情况,出于效率考虑,尽可能避免使用UniqueIdentifier型数据库作为主键值,但随着现代计算机计算速度越来越快,在中小型项目中使用UniqueIdentifier式主键也是一个选项。
四、使用业务字段联合主键基于DEPHI和POWERBUILDER等数据库工具开发C/S系统的数据库设计人员,习惯上用有业务意义的字段组合成复合主键做数据表主键。
使用业务主键当然有其与生俱来的好处,一般情况下数据库系统会在默认条件下建立聚簇索引,而且这个聚簇索引基于主键升序排列,当数据量比较小时,我们感觉不到这种差别,当数据量比较大时,这种基于主键定义的聚簇索引的优势就显现出来,这就使得数据表在每次存取数据时按照索引准确确认数据插入或更新的磁盘物理位置,减少磁头寻址时间,从而提高数据库性能,而且能够从业务意义上保证数据的完整性,增加程序的可靠性。
但是基于业务字段的联合索引,当业务字段选用比较多时会占用比较多的磁盘空间,而且索引页会占用更多的内存页面,从而导致查询命中率降低;另外使用业务主键,当涉及到主键数据的修改时,要在编程过程中记录新值和原值的关系表,在更新时又要进行新值和原值的比对,增加编写程序的复杂度。
五、时间序列+随机数主键采用精确到毫秒甚至钠秒级的时间和一个随机产生的两位数做主键,如200911282311528+两位随机数,不失为解决主键问题的一个有效办法。
这样产生的主键既避免了UniqueIdentifier 型字段做主键时的无序,又能有效避免自动增长型主键带来的诸如复制和数据导入的麻烦。
但在使用用户众多的网络实时系统中,在时间和空间上仍然不能保证唯一性的问题。
六、使用“COMB(Combine)”类型既然上面五种主键类型选取策略都存在各自的缺点,那么到底有没有好的办法加以解决呢?答案是肯定的。
通过使用COMB 类型(数据库中没有COMB类型,它是Jimmy Nilsson在他的“The Cost of GUIDs as Primary Keys”一文中设计出来的),可以在以上众多的主键策略之间采用中庸之道,找到一个很好的平衡点。
COMB数据类型的基本设计思路是这样的:既然UniqueIdentifier 数据因毫无规律可言造成索引效率低下,影响了系统的性能,那么我们能不能通过组合的方式,保留UniqueIdentifier的前10个字节,用后6个字节表示GUID生成的时间(DateTime),这样我们将时间信息与UniqueIdentifier组合起来,在保留UniqueIdentifier的唯一性的同时增加了有序性,以此来提高索引效率。
也许有人会担心UniqueIdentifier减少到10字节会造成数据出现重复,其实不用担心,后6字节的时间精度可以达到1/300秒,两个COMB类型数据完全相同的可能性是在这1/300秒内生成的两个GUID前10个字节完全相同,这几乎是不可能的!在SQL Server中用SQL命令将这一思路实现出来便是:DECLARE @aGuid UNIQUEIDENTIFIERSET @aGuid = CAST(CAST(NEWID() AS BINARY(10))+ CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER) 经过测试,使用COMB做主键比使用INT做主键,在检索、插入、更新、删除等操作上仍然显慢,但比Unidentifier类型要快上一些。