2012-03-29 76 views
3

我们有一个CreateDateTime PK表。插入程序是多线程的。显然,这不是线程安全的。有一个3列组合键,可以从表中的现有数据制作。这是一个日志表,流量预计很高。性能是主要关注的问题。主键选择的性能

我们的开发人员之一认为,由于SQL内部存储datetime(Epoch?)的方式,DateTime是出于性能原因的最佳PK。

我建议我们在3列中创建一个组合键。这个关键是否会对性能产生负面影响?

也有人建议我们使用GUID PK's。性能再次出现问题。

是否最好切换到组合键?如果是,我们如何解决/解释这些性能问题?

+1

'datetime'可能因为分辨率问题而不安全(这听起来很可能两个线程会同时登录)。具有强制性PK索引的复合键几乎肯定会增加RDBMS引擎的负载。我会用GUID去,因为它速度快,可靠,并且有足够的分辨率。 – dasblinkenlight 2012-03-29 13:22:56

+0

我想你应该阅读一些关于为sql server选择主键的文章。通过“pinaldave”查看本文。 候选键和主键之间的区别 http://blog.sqlauthority.com/2009/10/22/sql-server-difference-between-candidate-keys-and-primary-key -2/ – 2012-03-29 13:26:38

+0

'表现是主要的关注点'?你的意思是读取性能,写入性能,并发处理写入性能等,等等? – MatBailie 2012-03-29 13:42:09

回答

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相同的问题 - 只是稍微突出一点。

然后还有一个需要考虑的问题:表上的聚簇键将被添加到表上每个非聚簇索引中的每个条目上 - 因此,您确实希望确保它小到可能。通常情况下,具有超过250亿行的INT应该足以满足绝大多数表的要求 - 并且与GUID作为集群密钥相比,您可以为磁盘和服务器内存节省数百兆的存储空间。

快速计算 - 使用INT与GUID作为主要和聚集关键字:

  • 基本表与1'000'000行(3.8 MB与15.26 MB)
  • 6个的非聚集索引(22.89 MB与91.55 MB)

合计:25 MB vs. 106 MB - 这只是一张桌子!

还有一些值得思考的东西 - 金伯利特里普的优秀作品 - 读它,再读一遍,消化它!这真是SQL Server索引福音书。

至于组合键:在我看来,主要缺点是,希望所有表到现在引用此复合PK必须具有复合FK,其中全部为组合PK中定义的列。当你有很多需要使用这个组合键将子表连接到一个表的查询时,这会变得非常不方便。

DATEITME对于主键似乎不是一个好主意 - 在SQL Server中,DATETIME的准确度为3.33ms,因此在繁忙的系统中很可能会有非唯一值 - 对于PK来说不是个好主意!

如果性能是您的最高优先级,那么我肯定会推荐一个INT IDENTITY列(即使它是代理列)用于您的唯一聚集主键索引。

+2

非常好的思想答案 – HLGEM 2012-03-29 13:40:21