是否有理由永远不会使用主键列?

时间:2010-10-18 13:44:09

标签: sql-server database database-design indexing primary-key

我有一个例程,它将创建单独的表(Sql Server 2008)来存储我的应用程序生成的报告的结果(Asp.net 3.5)。每个报告都需要自己的表,因为表的列会根据报告设置而有所不同。一个表将包含10-5,000行之间,很少超过10,000行。

以下使用规则适用:

  • 存储后,数据永远不会更新。
  • 每当访问表的结果时,将检索所有数据。
  • 其他表格不需要与此表格进行连接。

知道这一点,有没有理由在表上创建PK索引列?这样做是否有助于以任何方式检索数据的性能,如果可以,这将超过插入数据时更新索引的额外负载(我知道10K记录的数量相对较少,但这个解决方案需要是能够扩展)。

更新:以下是有关正在处理的数据的更多详细信息,这些信息将在每个报告的一个表的当前设计决策中进行:

  • 表将记录一组数值(基于报告设置在运行时设置),这些数值对应于一组不同的参考varchar值(也根据报告设置在运行时设置)。
  • 每当检索到数据时,都需要在服务器上进行一些后处理,然后才能向用户显示输出(因此我将始终检索所有值)。

我还怀疑有人声称每次运行报告时都必须创建一个新表。但是,考虑到每次运行报告时都可能需要不同的列(数量,名称和数据类型),我看不到一个很好的选择。

我唯一能想到的是拥有一个ID列(标识ReportVersionID,对应另一个表),ReferenceValues列(varchar字段,包含所有引用值,按指定顺序,由一些分隔符分隔)和NumericValues列(与ReferenceValues相同,但对于数字),然后当我检索结果时,将所有内容放入系统中的专用对象,根据定义的分隔符分隔值)。这看起来更合适吗?

6 个答案:

答案 0 :(得分:3)

对于任何和所有数据表,主键都不是。没错,它们通常非常有用,放弃它们是不明智的。 然而,除了主要的速度任务(我同意可疑会受到积极影响)之外,也是唯一性的。为此,并重视你已经明显采取的考虑因素,我建议主键的唯一需要是控制表的预期唯一性。

<强>更新 您在评论中提到,如果您执行PK,它将包含一个目前不存在且不需要的Identity列。在这种情况下,我会建议反对PK。正如@RedFilter指出的那样,代理键永远不会添加任何值。

答案 1 :(得分:1)

我会保持简单,只需将转换为json或xml的报表结果存储在VARCHAR(MAX)列中

答案 2 :(得分:1)

数据完整性(主键和外键引用开始)最有用和最少强调(明确)的好处之一是它强制在您的数据和应用程序之间进行“按合同设计”;这样可以阻止 任何损坏 对您的数据造成很多类型的错误。这是一个如此巨大的胜利,并且隐含地认为这是理所当然的事情(它不是保护它的'数据库',而是你指定的完整性规则;放弃将数据暴露给不同程度的降级的规则。)

这对你来说似乎并不重要(因为你甚至没有讨论什么是可能的主键),你的数据似乎与系统的其他部分完全无关(因为你不会加入到任何部分)其他表);但仍然 - 如果所有事情都相同,我会正确建模数据,然后如果不使用主键(或其他数据完整性规则),如果追逐每一个性能,我会考虑将它们放入生产(并测试任何实际收益)。

至于评论创建表是一个性能损失 - 这是真的,但你没有告诉我们这些表有多临时?一旦创建,它们会在废弃之前大量使用吗?或者你打算为几十个读操作创建表。

如果您将大量使用这些表,如果您将提供清理机制来管理它们(在不使用时删除它们,选择它们等等)我认为动态创建表会很好(你可以在表格上分享更多细节;用例会很好)

有关其他解决方案的说明:

EAV model

除非满足非常具体的条件,否则

是可怕的(例如:灵活性是最重要的,自动化DDL太麻烦了)。远离它(或者非常非常善于预测您将需要处理哪些类型的查询严格验证前端数据)。

XML / BLOB方法

如果您将数据作为XML / BLOB在表示层使用,那么

可能是正确的选择(总是读取所有行,总是写出整个'对象',最后,如果您的表示层喜欢XML / BLOBS)

修改 此外,根据使用模式,主键可以确实提高了检索速度,如果我能读到数据不会被更新的事实'它将被写入一次并且读取很多时间'那么它很可能会超过更新插入索引的成本。

答案 3 :(得分:0)

对于给定报告的每次运行,它会是1个表,还是给定报告的所有运行都有一个表?换句话说,如果您有报告#1并且在不同的数据范围内运行5次,您将生成5个表,还是将所有5个报表运行存储在同一个表中?

如果要在同一个表中存储报告的所有5次运行,那么您需要过滤数据以使其适合相关的运行。在这种情况下,使用主键可以让你更快地执行过滤器的where语句。

如果要为报表的每次运行创建新表,则不需要主键。但是,当系统中的表数量增加时,您将遇到其他性能问题...假设您没有适当的东西来删除旧的数据/表。

答案 4 :(得分:0)

如果你真的没有将这些表用作一大块只读数据,那么你也可以将所有报告存储在一个表中,作为XML值。

答案 5 :(得分:0)

建立PK索引的列是什么?如果只是一个代理标识列,插入行时就不会有性能损失,因为它们会按顺序插入。如果它不是代理密钥,那么您可以确保您没有重复的条目,但仍然是有用的保证。

主键是否用于控制报表行的打印顺序?如果没有,那么您如何确保正确订购信息? (或者这只是一个数据表,无论何时生成报告,都会以某种方式求和?)

如果使用群集主键,则不会像使用非群集索引那样使用尽可能多的存储空间。

总的来说,我发现虽然并非每个表都需要一个主键,但是如果有一个表存在并没有什么坏处,并且由于正确的关系数据库设计需要所有表上的主键,所以总是包含它们是一种好习惯。 / p>