我们有一个包含CreateDateTime PK的表。执行插入的程序是多线程的。显然,这不是线程安全的。可以使用表中的现有数据创建3列复合键。这是一个记录表,预计流量会很高。性能是主要关注点。
我们的一位开发人员认为,由于SQL内部存储日期时间(Epoch?)的方式,出于性能原因,DateTime是最佳PK。
我建议我们用3列创建一个复合键。这一关键变化是否会对绩效产生负面影响?
还有人建议我们使用GUID PK。再一次,表现有问题。
最好切换到复合键吗?如果是,我们如何解决/解释这些性能问题?
答案 0 :(得分:4)
GUID似乎是您主键的自然选择 - 如果您真的必须,您可能会争辩将其用于表的PRIMARY KEY。我强烈建议不要使用GUID列作为群集密钥,默认情况下SQL Server会执行此操作,除非您明确告知不要。
你真的需要分开两个问题:
1)主键是一个逻辑结构 - 唯一且可靠地标识表中每一行的候选键之一。这可以是任何东西,真的 - 一个INT,一个GUID,一个字符串 - 选择对你的场景最有意义的东西。
2)集群密钥(在表上定义“聚集索引”的一列或多列) - 这是物理存储相关的东西,在这里,一个小的,稳定的,不断增加的数据类型是您的最佳选择 - INT或BIGINT作为您的默认选项。
默认情况下,SQL Server表上的主键也用作群集键 - 但这不一定是这样!我个人看到将以前基于GUID的主/群集密钥分解为两个单独的密钥 - GUID上的主(逻辑)密钥和单独的INT IDENTITY上的群集(排序)密钥(1, 1)专栏。
作为Kimberly Tripp - 索引女王 - 以及其他人已多次声明 - GUID作为聚类键不是最佳的,因为由于其随机性,它将导致大量页面和索引碎片并且通常表现不佳。
是的,我知道 - 在SQL Server 2005及更高版本中有newsequentialid()
- 但即使这样也不是真正完全顺序的,因此也会遇到与GUID相同的问题 - 只是不那么显着。< / p>
然后还有另一个需要考虑的问题:表格上的聚类键也会被添加到表格中每个非聚集索引的每个条目上 - 因此你真的想确保它尽可能小。通常,对于绝大多数表来说,具有2亿行的INT应该足够 - 并且与作为群集密钥的GUID相比,您可以在磁盘和服务器内存中节省数百兆的存储空间。
快速计算 - 使用INT与GUID作为主要和群集密钥:
TOTAL:25 MB vs. 106 MB - 这只是在一张桌子上!
更多值得思考的东西 - 金佰利特里普的优秀作品 - 阅读,再读一遍,消化它!这是SQL Server索引福音,真的。
对于复合键:我认为主要的缺点是所有想要引用此复合PK的表现在都必须具有复合FK,其中全部复合PK中定义的列。当你有很多需要将子表连接到具有这个复合键的表的查询时,这变得非常难以处理。
仅 DATEITME
对于主键似乎不是一个好主意 - 在SQL Server中,DATETIME
的准确度为3.33ms,因此在繁忙的系统中很有可能会有非独特的价值 - 对PK来说不是一个好主意!
如果性能是您的首要任务,那么我肯定会建议使用单个INT IDENTITY
列(即使它是代理列)来用于您的唯一群集主键索引。