Sql server 正在向表中添加INT,该表为';的主键是一个唯一标识符,用于连接表?

Sql server 正在向表中添加INT,该表为';的主键是一个唯一标识符,用于连接表?,sql-server,performance,join,indexing,uniqueidentifier,Sql Server,Performance,Join,Indexing,Uniqueidentifier,我的SQLServer2008数据库中有两个表:用户和项目 tblUser -------------------------- UserID uniqueidentifier Name nvarchar(50) etc.. tblItem -------------------------- ItemID uniqueidentifier ItemName nvarchar(50) etc.. tlmUserUserItem -------------

我的SQLServer2008数据库中有两个表:用户和项目

tblUser 
--------------------------
UserID    uniqueidentifier
Name      nvarchar(50)
etc..


tblItem 
--------------------------
ItemID    uniqueidentifier
ItemName      nvarchar(50)
etc..

tlmUserUserItem
----------------------------
ItemID      uniqueidentifier
UserID_A    uniqueidentifier
UserID_B    uniqueidentifier
我想将这些连接在一个多对多连接表中,该表将变得非常庞大(可能超过10亿行,因为应用程序逻辑需要共享用户-->项连接的统计信息)

连接表需要在UserID_A和UserID_B列上建立索引,因为查找是基于用户对其对等方的查询

我的问题是:

是否值得在用户表中添加一个自动递增INT作为非主键,然后在联接表中使用它?因此,用户表如下所示:

tblUser 
---------------------------------
UserID         uniqueidentifier
Name           nvarchar(50)
UserIDJoinKey  int  identity(1,1)
etc..
这样做,是否会更快地执行以下操作:

declare @ID int
select * from tblJoin where UserIDJoinKey_A = @ID or UserIDJoinKey_B = @ID
当联接表如下所示时:

tlmUserUserItem
-----------------------------------
ItemID             uniqueidentifier
UserIDJoinKey_A    int
UserIDJoinKey_B    int
与此相反:

tlmUserUserItem
----------------------------
ItemID      uniqueidentifier
UserID_A    uniqueidentifier
UserID_B    uniqueidentifier

提前感谢。

要想找到最好的解决方案,首先需要一些索引理论。SQL Server将其聚集索引数据存储在数据页的B+树中,每页可容纳约8K数据。 当您知道
uniqueidentifier
是每个键16个字节,而
int
是每个键4个字节时,这意味着
int
的每个索引页将有4倍多的键

要更快地连接
int
列,您很可能必须将其作为聚集索引。请注意,在如此大的表上添加额外的索引可能会对insert语句造成不必要的性能影响,因为有更多的信息要写入磁盘


这一切归结为对两种解决方案进行基准测试,并选择最适合您的解决方案。如果表的读取量更大,int列将提供更好的整体性能。

如果使用uniqueidentifier将操作连接到表时出现性能问题,请首先检查索引碎片。具有唯一标识符聚集索引的热表往往很快变得支离破碎。关于如何做到这一点,有很多好的信息

如果您能够将聚集索引移动到新的int列,并重写查询以使用新的int列而不是旧的uniqueidentifier,那么您最大的好处将是可以降低碎片率。这有助于避免在对表进行一系列写入操作后查询速度变慢


在大多数情况下,您不会注意到在uniqueidentifier列上处理联接操作的时间与MSSQL 2008中处理int的时间有很大差异——假设所有其他事情(包括碎片)都是相等的。

我可能误解了这一点,但是你想给每条记录添加一个标识和一个唯一标识符?当我看到您使用GUID时,我假设在用户联机时会合并脱机功能,或者选择GUID是因为一些无关的原因。这个原因会妨碍您在每个项目上正确实现标识列

如果没有具体的原因说明为什么需要在标识上使用guid,我会说将guid一起废弃。它会使您的表、索引膨胀,并降低连接速度。如果我有误解,请让我知道,我道歉

@MikeM

我个人每次都会选择一个uniqueidentifier而不是int作为表的主键。不过,我会使用NEWSEQUENTIALID()而不是NEWGUID()来确保索引碎片更少

我做出这个选择的原因很简单:

整数很容易混淆,在有多个外键的表中,“意外”将值放入错误字段的几率太高。您永远不会看到这个问题,因为所有标识列的种子都是1,所以大多数表中的每个表都有匹配的整数值。通过使用uniqueidentifier,我绝对保证对于具有外键的列的所有实例,我在其中放置的值都是正确的,因为它引用的表是唯一能够具有该唯一标识符的表

而且。。。在代码中,您的参数都是int,这再次使您有可能意外地将错误的值放入错误的参数中,并且您永远不会知道有任何不同。通过使用唯一标识符,您再次保证了正确的引用

试图追踪由交叉传递的整数引起的错误是一件阴险的事情,最糟糕的是,直到为时已晚,数据已经被破坏得太厉害,你永远无法解开,你才知道问题已经发生。只需要一个交叉匹配的整型字段,就有可能创建数百万个不一致的行,除非您“碰巧”尝试插入一个引用表中不存在的值,否则您不会意识到这些不一致的行。。。到那时可能已经太晚了