位置: 编程技术 - 正文

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

编辑:rootadmin
因为主键可以唯一标识某一行记录,所以可以确保执行数据更新、删除的时候不会出现张冠李戴的错误。当然,其它字段可以辅助我们在执行这些操作时消除共享冲突,不过就不在这里讨论了。主键除了上述作用外,常常与外键构成参照完整性约束,防止出现数据不一致。所以数据库在设计时,主键起到了很重要的作用。 常见的数据库主键选取方式有: 自动增长字段 手动增长字段 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自动增长是什么意思)

  • 发放上年年终奖个税
  • 会计所得税公式怎么算
  • 啥叫反倾销税
  • 继续教育容易过吗
  • 商业保理怎么账务处理
  • 小规模零税率申报流程
  • 出租房屋收取的水电费如何记账
  • 清算报告与清算方案区别
  • 进销存明细账怎么填写
  • 购入设备发生的运输费计入什么科目
  • 企业股权资本的组成
  • 房地产企业承担的债务
  • 资本溢价能不能退还股东呢
  • 以前的货款用银行账户吗
  • 律师事务所计提准备金的标准
  • 企业亏损会影响利润吗
  • 股权转让 分期付款
  • 如何购买车辆保险
  • 化妆品消费税是从价还是从量
  • 高亮!这些发票不能抵扣增值税
  • 销售费用变动率公式
  • 支付车辆保险费及车船税会计科目
  • 增值税价外费用不包括
  • 学校维修维护费包括哪些
  • 股票交易的印花税和手续费是多少
  • 核定征收的个税怎么算
  • 去年开的增值税普通发票今年可以作废吗
  • 在建工程增值税可以抵扣吗
  • 财务负责人的岗位
  • 公司开办期间账务处理
  • 应收账款怎么做分录
  • 实收资本或股本账户属于企业的什么账
  • win11如何设置开机自启动软件
  • PHP调用API
  • 水利建设基金是税还是费
  • php字符串赋值
  • 企业代付个人所得税计算公式
  • 建筑业的账务处理办法
  • mxnet github
  • 马拉喀什的历史背景
  • 施工方可以向建设单位借款么
  • 增值税加计抵减企业所得税如何处理
  • 简述gnss数据处理流程
  • 蜜蜂皇vs
  • 预缴的附加税怎么填表抵减
  • 小型企业资产负债表
  • 前端开发配置
  • 一般纳税人两费附加减免规定
  • 逾期未退押金是否确认收入
  • python绘制散点图的函数
  • 配送中心适合哪种类型的企业
  • 《开具红字增值税专用发票通知单》
  • 什么是虚开增值发票
  • 重复报销怎么写情况说明
  • 管理费用结转到哪个科目
  • 记账凭证后面附发票第几联
  • 当月没开发票
  • 交去年的企业所得税吗
  • 生产型企业账务处理方法
  • 小规模其他业务收入交多少税率
  • 提交印花税会计分录
  • 年底需要结转的会计科目
  • 投资性房地产是固定资产吗
  • win8.1开机密码忘了
  • win10edge浏览器默认主页网址
  • windows server 2008 r2怎么用u盘启动
  • ubuntu安装lamp
  • webinstall.exe - webinstall是什么进程
  • windows7旗舰版开机声音
  • win8怎样恢复系统
  • js获取秒数
  • javascript数据结构
  • jquery实现仿新浪微博带动画效果弹出层代码(可关闭、可拖动)
  • nodejs使用视频教程
  • jQuery EasyUI Pagination实现分页的常用方法
  • python编程输出汉字
  • 目的地查验和口岸查验费用一样吗
  • 怎么注册用户名短的淘宝账号
  • 一般纳税人提供公共交通运输服务免征增值税
  • 企业房产如何过户给个人
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设