AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 135122
Accepted
Matthew
Matthew
Asked: 2016-04-13 19:38:47 +0800 CST2016-04-13 19:38:47 +0800 CST 2016-04-13 19:38:47 +0800 CST

SYSUTCDATETIME 是安全的主键吗?

  • 772

我有一个连续修改的已处理事件表。处理时间的 utc 时间和 eventId。

使用 SYSUTCDATETIME() 作为我的主键是否安全?我可以轻松地使用代理键,但感觉很有趣。

sql-server sql-server-2014
  • 1 1 个回答
  • 795 Views

1 个回答

  • Voted
  1. Best Answer
    Solomon Rutzky
    2016-04-13T20:10:07+08:002016-04-13T20:10:07+08:00

    (请注意问题的原始措辞是:“SYSUTCDATETIME 是安全的聚集索引吗?”)

    “安全”到底是什么意思?聚簇索引不需要是唯一的,因此它是“安全的”,因为它不会破坏任何东西。但它不能是主键,因为不能保证它是唯一的。只需尝试以下操作,您就会看到从函数返回的值在所有行中都是相同的:

    SELECT SYSUTCDATETIME(), * FROM sys.objects;
    

    那么问题来了:使用SYSUTCDATETIME()而不是 an到底能得到IDENTITY什么?我假设您正在使用一个DATETIME28 字节的列,但您很可能会INT为该IDENTITY列使用 4 个字节。

    因此,我会按原样使用INT填充过孔:IDENTITY

    • 更小(4 个字节而不是 8 个字节;在具有唯一值的理想情况下为 8 个字节,但是当存在重复项时,“uniquifier”值将添加到任何重复的行,即额外的 4 个字节)
    • 保证唯一(不仅对聚簇索引更好,而且有资格成为 PK)。
    • 无论如何它们基本上都是相同的顺序(尽管有时它们可​​能不会按顺序匹配)

    更新

    不,我个人不会相信一个值,即使具有如此高分辨率DATETIME2,作为主键,因为两个操作仍然有可能在同一微秒内发生。并且,您不能保证将来任何时候某人或某个进程都不会在单个语句中插入超过 1 条记录。

    更新 2

    @ypercubeᵀᴹ 在下面的评论中提出了一个很好的观点(我在这里提到的评论很快就会神奇地消失 ;-):

    您可以将日期时间列用于聚簇索引,将标识列用于 PK。(这有时很好,如果您的所有或几乎所有查询都依赖于按日期时间排序。因此两个订单偶尔不匹配不会影响性能。)

    是的,这有时是一个不错的选择,但由于聚集索引键被复制到非聚集索引中,它并非没有潜在后果:

    • 如果这张表上只有一个非聚集索引,那么无论哪一种索引占用的空间都差不多。但是因为聚簇索引键最终必须是唯一的(至少在内部),因为它们是非聚簇索引的 RowID,对于所有具有重复DATETIME2值的行,将添加额外的 4 字节“uniquifier”。它将被添加两次:一次添加到聚集索引,一次添加到 IDENTITY PK 的非聚集索引。

    • 如果有多个非聚集索引,那么对空间使用的影响将是:

      (最少 4 个字节 + 任何重复的聚簇索引键值 4 个字节)
      * number_of_indexes
      * rows_in_table(如果使用过滤索引则更少)

      这些数字对某些人来说可能看起来很小,但如果我们处理数亿行,它们就会加起来。对于那些错误地认为“磁盘很便宜”的人,请考虑 a)企业存储并不便宜,b)索引维护等磁盘操作也不便宜(SSD 的问题不大,但仍然如此)。有关数据建模决策的下游影响的更详细分析,请参阅我在 SQL Server Central 上发表的以下文章:Disk Is Cheap!奥利?(该站点需要免费注册才能查看内容)。

    这并不是说“不要做”,而是“只有收益大于成本时才做”。

    更新 3

    为了完整起见,我应该提到使用DATETIME2值来分离个体INSERT和/或UPDATE语句的一个问题是它们并不像它们看起来那样精细。这是“分辨率”和“精度”之间的问题。的“精度”DATETIME2是小数点后 7 位。但这并不意味着所表示的最细粒度的时间值会在下一个值发生时递增。这就像DATETIME精确到毫秒的值一样,你永远不会得到一个在毫秒位置只有 0、3 或 7 的值:

    SELECT CONVERT(DATETIME, '2016-04-14 20:30:40.121'), -- 2016-04-14 20:30:40.120
           CONVERT(DATETIME, '2016-04-14 20:30:40.122'), -- 2016-04-14 20:30:40.123
           CONVERT(DATETIME, '2016-04-14 20:30:40.128'); -- 2016-04-14 20:30:40.127
    

    与值类似DATETIME2,有时调用SYSUTCDATETIME()是完全准确的。但是由于该值不会在下一微秒刷新,因此报告的值将保持不变一段时间,直到下次刷新为止。这就是为什么@Paul 在对问题的评论中发布的简单测试会违反 PK,即使这两个INSERT语句可以说至少相隔 1 微秒。

    有关更多详细信息,请参阅以下 Stack Overflow 答案,包括指向 CodeProject.com 上的项目的链接,该项目具有可在 SQLCLR 中使用以克服此限制的代码:

    SQL Server CLR 集成未按预期调用系统时间

    • 11

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve