位置: 编程技术 - 正文

小议sqlserver数据库主键选取策略(sql server数据库使用)

发布时间:2024-02-26
因为主键可以唯一标识某一行记录,所以可以确保执行数据更新、删除的时候不会出现张冠李戴的错误。当然,其它字段可以辅助我们在执行这些操作时消除共享冲突,不过就不在这里讨论了。主键除了上述作用外,常常与外键构成参照完整性约束,防止出现数据不一致。所以数据库在设计时,主键起到了很重要的作用。 常见的数据库主键选取方式有: 自动增长字段 手动增长字段 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表。最后更新OderDetail表。但是,为了确保数据的一致性,Order与 OrderDetail在更新时必须在事务保护下同时进行,即确保两表同时更行成功。显然它们是相互矛盾的。(此处表述有错误。吕震宇 -6-) 【补充-6-】--------------------------------------------- 听棠.NET指出:主档放在事务中提交时,通过@@IDENTITY 就可以取到生成值的,因此可以传给明细当外键用,而且在事务发生错误回滚时,主档记录也会被回滚取消的。 吕震宇补充:使用自动增长字段会增加网络的roundTrip。尽管可以使用@@IDENTITY取得主键的值,但在更新过程中,不得不增加一次数据往返(以C/S结构为例): 1、客户端发送开始事务命令 2、客户端提交主表更新 3、服务器返回@@IDENTITY 4、客户端根据返回的主键更新从表缓冲 5、客户端将从表提交服务器更新 6、客户端提交事务 在这里多了一次往返就会增加了事务处理的时间。降低并发性能。 如果不用自动增长型字段,将是以下情景: 1、客户端发送开始事务命令 2、客户端提交主表更新 3、客户端提交从表更新 4、客户端提交事务 因此我不赞成使用自动增长型字段作为主键与外键链接的纽带。 ------------------------------------------------ 除此之外,当我们需要在多个数据库间进行数据的复制时(SQL Server的数据分发、订阅机制允许我们进行库间的数据复制操作),自动增长型字段可能造成数据合并时的主键冲突。设想一个数据库中的Order表向另一个库中的Order表复制数据库时,OrderID到底该不该自动增长呢? ADO.NET允许我们在DataSet中将某一个字段设置为自动增长型字段,但千万记住,这个自动增长字段仅仅是个占位符而已,当数据库进行更新时,数据库生成的值会自动取代ADO.NET分配的值。所以为了防止用户产生误解,建议大家将ADO.NET中的自动增长初始值以及增量都设置成-1。此外,在ADO.NET中,我们可以为两张表建立DataRelation,这样存在级联关系的两张表更新时,一张表更新后另外一张表对应键的值也会自动发生变化,这会大大减少了我们对存在级联关系的两表间更新时自动增长型字段带来的麻烦。 二、手动增长型字段 既然自动增长型字段会带来如此的麻烦,我们不妨考虑使用手动增长型的字段,也就是说主键的值需要自己维护,通常情况下需要建立一张单独的表存储当前主键键值。还用上面的例子来说,这次我们新建一张表叫IntKey,包含两个字段,KeyName以及KeyValue。就像一个HashTable,给一个KeyName,就可以知道目前的KeyValue是什么,然后手工实现键值数据递增。在SQL Server中可以编写这样一个存储过程,让取键值的过程自动进行。代码如下: 这样,通过调用存储过程,我们可以获得最新键值,确保不会出现重复。若将OrderID字段设置为手动增长型字段,我们的程序可以由以下几步来实现:首先调用存储过程,获得一个OrderID,然后使用这个OrderID填充Order表与OrderDetail表,最后在事务保护下对两表进行更新。 使用手动增长型字段作为主键在进行数据库间数据复制时,可以确保数据合并过程中不会出现键值冲突,只要我们为不同的数据库分配不同的主键取值段就行了。但是,使用手动增长型字段会增加网络的RoundTrip,我们必须通过增加一次数据库访问来获取当前主键键值,这会增加网络和数据库的负载,当处于一个低速或断开的网络环境中时,这种做法会有很大的弊端。同时,手工维护主键还要考虑并发冲突等种种因素,这更会增加系统的复杂程度。 三、使用UniqueIdentifier SQL Server为我们提供了UniqueIdentifier数据类型,并提供了一个生成函数NEWID( ),使用NEWID( )可以生成一个唯一的UniqueIdentifier。UniqueIdentifier在数据库中占用个字节,出现重复的概率非常小,以至于可以认为是0。我们经常从注册表中看到类似 {F0EB--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字段也存在严重的缺陷:首先,它的长度是字节,是整数的4倍长,会占用大量存储空间。更为严重的是,UniqueIdentifier的生成毫无规律可言,要想在上面建立索引(绝大多数数据库在主键上都有索引)是一个非常耗时的操作。有人做过实验,插入同样的数据量,使用UniqueIdentifier型数据做主键要比使用Integer型数据慢,所以,出于效率考虑,尽可能避免使用 UniqueIdentifier型数据库作为主键键值。 四、使用“COMB(Combine)”类型 既然上面三种主键类型选取策略都存在各自的缺点,那么到底有没有好的办法加以解决呢?答案是肯定的。通过使用COMB类型(数据库中没有COMB类型,它是Jimmy Nilsson在他的“The Cost of GUIDs as Primary Keys”一文中设计出来的),可以在三者之间找到一个很好的平衡点。 COMB数据类型的基本设计思路是这样的:既然UniqueIdentifier数据因毫无规律可言造成索引效率低下,影响了系统的性能,那么我们能不能通过组合的方式,保留UniqueIdentifier的前个字节,用后6个字节表示GUID生成的时间(DateTime),这样我们将时间信息与UniqueIdentifier组合起来,在保留UniqueIdentifier的唯一性的同时增加了有序性,以此来提高索引效率。也许有人会担心UniqueIdentifier减少到字节会造成数据出现重复,其实不用担心,后6字节的时间精度可以达到1/秒,两个COMB类型数据完全相同的可能性是在这1/秒内生成的两个GUID前个字节完全相同,这几乎是不可能的!在SQL Server中用SQL命令将这一思路实现出来便是: 经过测试,使用COMB做主键比使用INT做主键,在检索、插入、更新、删除等操作上仍然显慢,但比Unidentifier类型要快上一些。关于测试数据可以参考我年7月日的随笔。 除了使用存储过程实现COMB数据外,我们也可以使用C#生成COMB数据,这样所有主键生成工作可以在客户端完成。C#代码如下: 结语 数据库主键在数据库中占有重要地位。主键的选取策略决定了系统是否高效、易用。本文比较了四种主键选取策略的优缺点,并提供了相应的代码解决方案,希望对大家有所帮助。

推荐整理分享小议sqlserver数据库主键选取策略(sql server数据库使用),希望有所帮助,仅作参考,欢迎阅读内容。

小议sqlserver数据库主键选取策略(sql server数据库使用)

文章相关热门搜索词:sql server 数据库介绍,sql server数据,sql server数据,sqlserverce,sqlserver数据库,sqlserver数据库,sqlserver数据库,sqlserver,内容如对您有帮助,希望把文章链接给更多的朋友!

sqlserver自动增长列引起的问题解决方法 有两个结构完全相同的表,由其中一个表插入另一个表中指定条件的数据,报如下错误:仅当使用了列列表并且IDENTITY_INSERT为ON时,才能为表'*'中的标识

sqlserver 存储过程动态参数调用实现代码 只是做笔记,没什么!!--创建测试表CREATETABLE[dbo].[Student]([ID][int]IDENTITY(1,1)NOTNULLPRIMARYKEY,[Name][nvarchar]()NOTNULLDEFAULT(''),[Age][int]NOTNULLDEFAULT(0),[Sex][bit]NOTNUL

通过分析SQL语句的执行计划优化SQL 如何干预执行计划--使用hints提示基于代价的优化器是很聪明的,在绝大多数情况下它会选择正确的优化器,减轻了DBA的负担。但有时它也聪明反被聪明

标签: sql server数据库使用

本文链接地址:https://www.jiuchutong.com/biancheng/348865.html 转载请保留说明!

上一篇:SQL语句 一个简单的字符串分割函数(如果一个sql语句中包括两个名字)

下一篇:sqlserver自动增长列引起的问题解决方法(sql自动增长是什么意思)

  • 税收筹划分为哪几类
  • 税收 特征
  • 购买财务软件如何做凭证
  • 小规模税控设备维护费怎么填申报表格
  • 纳税人财务会计报表报送管理办法
  • 公司补缴社保协议书
  • 个体开票
  • 进口货物的应纳增值税
  • 增值税采用零税率政策的内容
  • 抹掉的零头怎么入账
  • 公司股东投资是负债吗
  • 职工福利基金提取规定
  • 房屋购买安装电梯可以抵扣吗?
  • 建安业核定征收利润率
  • 营改增后建筑业税率变化情况
  • 填报企业所得税资产总额怎么填
  • 外币业务汇兑损益根据业务划分为
  • 分包给总包开什么发票
  • 金蝶的币别和汇率怎么取消
  • 小规模纳税人代账一年多少钱
  • 企业所得税税率2.5% 5% 25%
  • 外出经营地预交税金归主管税务所管吗
  • 公司增资减资法条
  • 进料进口
  • php初始化会话
  • neoCapture.exe - neoCapture是什么进程 有什么用
  • 建筑公司收到工程款需要交哪些税
  • 公司为什么要签劳务协议
  • 增值税发票红冲后税款怎么办
  • 房地产企业前期物业费可否税前扣除
  • config.cfg是什么文件
  • 预算周转金会计怎么做账
  • 纳税人转登记期限
  • 房地产开发公式
  • 高通 adc
  • vue如何实现打印
  • electron-vue官网
  • 固定资产家具用具包括什么
  • 记账凭证中的会计科目错误导致账簿错误的更正法
  • 资产减值损失和资产减值准备
  • 营改增后还有企业所得税吗?
  • 前端面试题汇总.pdf
  • python中np.array用法
  • mysql数据库性能监控
  • 税法中减除和减退的区别
  • 综合所得算税公式
  • mysql查询在什么之间
  • 主营业务收入明细科目
  • 发票冲红重开摘要如何写合适?
  • 坏账准备的计提方法有哪些
  • 融资租赁取得的机器设备的账务处理
  • 增值税起征点有多少
  • 企业取得生产或制造某项财产物资时
  • 支付给外包公司的工资和保险费
  • 其他综合收益属于什么科目借贷
  • 进销项月末结转吗
  • 厂家给的促销费可以退吗
  • 年化收益率怎么算
  • sqlserver 字符串包含
  • sql server存储过程写法
  • 数据库表的行数
  • win8的应用商店
  • ubuntu鼠标不能移动
  • mac迁移助理是什么意思啊
  • rhel配置网卡文件和图形界面
  • linux邮件设置方法
  • win10系统自带虚拟机怎么用
  • linux安装docker-compose
  • vuejs环境搭建
  • 浅谈会计诚信与职业道德论文
  • linux lvm配置
  • 批处理 leq
  • jQuery UI结合Ajax创建可定制的Web界面
  • js基于什么
  • 西安市电子税务局
  • 广东国家电子税务全电发票
  • 深圳营业执照办理咨询电话
  • 关联企业签订劳动合同的次数可以累计吗
  • 主要领导成员是指
  • 遂宁市国家税务局
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号