我正在与一个想要将时间戳添加到一堆表的客户端一起工作,以便他们可以按时间顺序对这些表中的记录进行排序。所有表都有一个自动递增的整数字段作为其主键(id)。
(简单)想法 - 节省开销/存储并依赖主键按时间顺序排序字段。当然这有效,但我不确定这种方法在声音数据库设计中是否可以接受。
优点:每条记录需要更少的存储空间,更简单的VO类等等。
Con:它暗示了该字段的特征,即一个简单的标识符,其定义不以任何方式定义或保证它应该/将如此起作用。
假设为了我的问题,DB表定义是一成不变的。仍然 - 这在最佳实践方面是否可以接受?
谢谢
你要求“最佳实践”,而不是“不可怕的做法”,所以: 没有,您不应该依赖自动增量主键来建立年表。有一天你要引入数据库设计的改变,这将会破坏。我已经看到它发生了。
日期时间列,其默认值为 GETDATE()
具有非常小的开销(大约和整数一样多)并且(更好地)告诉你不仅仅是序列而且 实际日期和时间,这往往是无价的。即使在柱上保持索引也相对便宜。
这几天,我 总是 放一个 CreateDate
列数据对象连接到现实世界事件(例如帐户创建)。
编辑添加:
如果精确的时间顺序对您的应用程序至关重要,则不能依赖于自动增量或时间戳(因为无论分辨率有多高,总会有相同的时间戳)。你可能不得不做一些特定于应用程序的东西。
您可以通过对ID列进行排序,在短期内实现相同的目标。这样可以更好地添加额外的数据来实现相同的结果。我不认为任何人看到数据表并且知道按时间顺序看到它是一个标识列时会让人感到困惑。
然而,我看到了一些缺点或限制。
- 如果有人重新播种列,则按时间顺序排序可能会混乱
- 没有附加数据,无法确定日期的年表
- 如果系统接受新的非时间顺序数据,此设置将阻止您按时间顺序排序
基于对这些“限制”的现实评估,您应该能够建议正确的方法。
对于egrunin的回答,对这些行的持久性或处理逻辑的更改可能导致以非顺序或非确定的方式将行插入数据库。您可以实现一个并行化的文件处理器,一旦线程完成转换就会将一行抛入DB,这可能是在另一个线程完成处理文件中较早出现的行之前。使用ORM进行记录持久性可能会导致类似的行为; ORM可能只维护一个等待持久性的对象图的“包”(无序集合),并随机抓取它们以便在被告知“刷新”其对象缓冲区时将它们持久保存到数据库中。
在任何一种情况下,相信自动增量列告诉你记录进入系统的顺序是坏juju。它可能会也可能不会告诉您记录他的数据库的顺序;这取决于数据库的实现。
自动递增ID将让您了解布拉德指出的订单,但做得正确 - 如果您想知道何时添加了某些内容,请使用日期时间列。那么你不仅可以按时间顺序排序,还可以应用过滤器。
不要这样做。您永远不应该依赖ID列的实际值。像黑盒一样对待它,只对键查找有用。
你说“每条记录需要更少的存储空间”,但这有多重要?我们谈论的行有多大?如果你有200字节的行,那么另外4个字节可能并不重要。
没有测量就不要优化。首先让它正常工作,然后进行优化。
@MadBreaker
如果您需要知道使用自动增量创建列顺序的顺序,则需要单独处理,但是如果您想知道插入的日期和时间,则使用datetime2。
如果您不允许更新或删除,则可以保证按时间顺序排列,但如果您希望时间控制为select,则应使用datetime2。
您没有提到您是在单个数据库还是群集上运行。如果你是聚集的,要警惕增量实现,因为你并不总是保证事情会以你自然想到的顺序出现。例如,Oracle序列可以缓存下一个值的组(取决于您的设置),并为您提供1,3,2,4,5种列表...