我知道这是主观的,但我想了解人们的意见,并希望在设计 sql server 表结构时可以应用一些最佳实践。
我个人认为,在固定(最大)长度的 varchar 上键入表是不行的,因为这意味着必须在使用它作为外键的任何其他表上传播相同的固定长度。使用int
,将避免必须在整个板上应用相同的长度,这必然会导致人为错误,即 1 个表有varchar (10)
, 和另一个varchar (20)
.
这对于最初的设置来说听起来像是一场噩梦,而且意味着未来的表维护也很麻烦。例如,假设键控 varchar 列突然变成 12 个字符而不是 10 个。您现在必须去更新所有其他表,这可能是多年后的一项艰巨任务。
我错了吗?我在这里错过了什么吗?我想知道其他人对此有何看法,以及坚持使用 int 作为主键是否是避免维护噩梦的最佳方法。
选择主键时通常也会选择聚集键。他们两个经常被混淆,但你必须理解其中的区别。
主键有逻辑性business元素。主键被你的应用程序用来标识一个实体,关于主键的讨论主要是是否使用自然键 or 代理键。这些链接更详细,但基本思想是自然键源自现有的实体属性,例如ssn
or phone number
,而代理键对于业务实体没有任何意义,例如id
or rowid
他们通常是这样的类型IDENTITY
或某种 uuid。我个人的观点是,代理键优于自然键,并且选择应该始终是仅限本地应用程序的身份值,以及任何类型的分布式数据的指南。主键在实体的生命周期内永远不会改变。
聚集键是定义表中行的物理存储的键。大多数时候它们与主键(逻辑实体标识符)重叠,但这实际上并没有强制执行或要求。当两者不同时,意味着表上存在实现主键的非聚集唯一索引。聚集键值实际上可以在行的生命周期内发生变化,从而导致该行在表中物理移动到新位置。如果必须将主键与聚集键分开(有时确实如此),那么选择一个好的聚集键比选择主键要困难得多。驱动集群键设计的主要因素有两个:
- 流行的数据访问模式.
- The 存储注意事项.
数据访问模式。通过这个我了解了表的查询和更新方式。请记住,聚集键决定表中行的实际顺序。对于某些访问模式,某些布局在查询速度或更新并发性方面具有很大的不同:
当前数据与存档数据。在许多应用中,属于当前月份的数据被频繁访问,而过去的数据则很少被访问。在这种情况下,表设计使用表分区按交易日期,通常使用滑动窗口算法。当月分区保留在位于热快速磁盘的文件组上,存档的旧数据被移动到托管在更便宜但速度较慢的存储上的文件组。显然,在这种情况下,聚集键(日期)不是主键(事务 ID)。两者的分离是由规模要求驱动的,因为查询优化器将能够检测到查询只对当前分区感兴趣,甚至不查看历史分区。
先进先出队列式处理。在这种情况下,表有两个热点:发生插入的尾部(入队)和发生删除的头部(出队)。聚集键必须考虑到这一点并组织表以物理分离磁盘上的尾部和头部位置,以便允许入队和出队之间的并发性,例如。通过使用排队顺序键。在pure队列中此聚集键是唯一的键,因为表上没有主键(它包含messages, not entities)。但大多数时候队列并不是纯粹的,它还充当实体的存储,以及实体之间的线路queue和table是模糊的。在这种情况下,还有一个主键,它不能是聚集键:实体可以重新排队,从而更改排队顺序聚集键值,但它们不能更改主键值。未能看到分离是用户表支持的队列如此难以正确处理并充满死锁的主要原因:因为入队和出队是在表中交错发生的,而不是集中在队列的尾部和头部。
相关处理。当应用程序设计良好时,它将在其工作线程之间划分相关项目的处理。例如,处理器被设计为具有 8 个工作线程(假设与服务器上的 8 个 CPU 相匹配),因此处理器会在它们之间对数据进行分区,例如。工作人员 1 仅选取名为 A 到 E 的帐户,工作人员 2 F 到 J 等。在这种情况下,表实际上应按帐户名称(或最左边位置是帐户名称的第一个字母的复合键)进行集群,以便工作人员在表中本地化他们的查询和更新。这样的表将有 8 个不同的热点,围绕每个工作人员当前集中的区域,但重要的是它们不重叠(无阻塞)。这种设计在高吞吐量 OLTP 设计和 TPCC 基准测试负载中很普遍,其中这种分区也反映在缓冲池中加载的页面的内存位置(NUMA 局部性),但我离题了。
存储注意事项。聚集键width对表的存储有巨大的影响。对于一个键来说,它占用了 B 树的每个非叶页中的空间,因此较大的键将占用更多的空间。其次,通常更重要的是,聚集键被每个非聚集键用作查找键,因此every非聚集键必须存储每行的聚集键的完整宽度。这就是像 varchar(256) 和 guid 这样的大型聚集键成为聚集索引键的糟糕选择的原因。
此外,键的选择也会影响聚集索引碎片,有时会极大地影响性能。
这两种力量有时可能是对立的,数据访问模式需要某个大的聚集键,这会导致存储问题。在这种情况下,当然需要平衡,但没有神奇的公式。您进行测量和测试以达到最佳状态。
那么我们能从这一切中得到什么呢?始终首先考虑聚集键,它也是表单的主键entity_id IDENTITY(1,1) NOT NULL
。将两者分开并在适当时相应地组织表(例如按日期分区)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)