Sql 这是存储在表中的反模式:下一个主键吗

Sql 这是存储在表中的反模式:下一个主键吗,sql,design-patterns,documentation,Sql,Design Patterns,Documentation,我正在寻找一些关于为什么这是(或不是)一个糟糕设计的文档 第三方vedor的代码使用一个单独的表来存储所有表的主键 __KeyTable____ NextKey TableName 45 Table1 1003 Table2 90 Table3 __Table1____ id Column1 Column2 45 ... ... CREATE TABLE [dbo].[Table1]( [id] [int] NOT NULL,

我正在寻找一些关于为什么这是(或不是)一个糟糕设计的文档

第三方vedor的代码使用一个单独的表来存储所有表的主键

__KeyTable____
NextKey  TableName
45       Table1
1003     Table2
90       Table3

__Table1____
id  Column1  Column2
45  ...      ...

CREATE TABLE [dbo].[Table1](
    [id] [int] NOT NULL,        /* <---- IDENTITY(1,1) is not present */
    [Column1] [nvarchar](1) NULL,
    [Column2] [nvarchar](1) NULL
 CONSTRAINT [PK_WFDATASET] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)
\uuuu键表____
NextKey表名
45表1
1003表2
90表3
__表1____
id第1列第2列
45  ...      ...
创建表[dbo]。[Table1](

[id][int]NOT NULL,/*使用IDENTITY及其工作类的一个副作用是可能会出现值序列中的差异。这不是一个bug;这是出于设计

但有些应用程序要求您对所使用的每个ID号进行说明。想想财务管理系统,您可能需要对从时间开始到时间结束的每个发票号或每个支票号进行说明。使用键表(如示例中的键表)是一种确保表中没有空白的方法值的顺序

另一种可能性是,您的应用程序是从一个更旧、更简单的系统中成长起来的,该系统不基于SQL dbms(因此没有任何类似标识的功能)

我能想到的唯一简单的原因是,您的应用程序允许在不同时使用ON DELETE CASCADE的情况下删除行(这可能会引入间隙),这是因为您的表没有外键。使用键表和使用ON DELETE CASCADE声明的外键之间没有技术冲突。(试试看。)


数据库设计者的一条经验法则是“不要用过程代码替换DDL,”这意味着,当您可以将外键声明为DELETE CASCADE时,通常不会在每个表上写入三个触发器。很少有例外;很可能这不是其中之一。

好吧,这是一个糟糕的设计,因为您需要在针对表1的事务期间锁定KeyTable中的一行。也就是说,当您运行事务时:

  • 从KeyTable获取值
  • 将递增的值存储在KeyTable中
  • 在表1中插入新行
  • 没有并发会话可以这样做。这对可伸缩性是一个很大的惩罚,因为插入到Table1的所有会话都被强制排队并串行访问KeyTable

    然而,任何实现良好的标识功能都只需要非常短暂地锁定标识分配器,从而提高吞吐量。这发生在内存中。标识缓存一组接下来的10个标识值,插入行的会话从该集合中提取


    使用IDENTITY还可以减少存储引擎级别上的锁争用,这在将KeyTable中的更改写回磁盘时是必需的。

    谢谢您,这一点说得很好(非常有用),我正在寻找一篇MSDN文章或Dailywtf.com类型的反模式,我可以指出。我也感谢您的输入。您是对的,这不是预数据库,最早的版本是用ASP.Net编写的,也不是设计编写的,只是糟糕的代码。您知道我写的任何MSDN文章或Dailywtf.com类型的反模式吗指向什么?我不认为这是一个反模式。如果你需要一个没有间隙的序列,你必须实现这样的东西。现在,这对你的应用程序来说可能是一个糟糕的设计,但这并不意味着它是一个反模式。间隙问题没有得到解决。显示给用户的外部id是在鼠标上生成的通过ajax(您读得对)进行更新,如果24小时后未使用,则会删除它们,并生成4个xml文件(您读得对)。这保证了间隙始终存在。大多数表用于其他id,这些id从未显示给用户。除此之外,键还存储了表的上一个使用月份的xml文件的文件路径(您读对了):Table1.month.3。“Workflow maker”是一个糟糕的产品啊。您应该有。