Sql server 2005 为最快查询创建guid主键选择guid所在位置(guid1、guid2、guid3…)

Sql server 2005 为最快查询创建guid主键选择guid所在位置(guid1、guid2、guid3…),sql-server-2005,Sql Server 2005,需要将GUID用作主键。我这样想对吗 ProductID UNIQUEIDENTIFIER NOT NULL ROWGUIDCOL DEFAULT (NEWSEQUNTIALID()) PRIMARY KEY CLUSTERED 将为where子句提供最快的select productid(guid1,guid2,…,guidn) 而且不会恶化非集群的性能 像“某物*”这样的自然键 独立选择。表只供用户查询,并从头开始以编程方式创建/重新创建。聚集索引最适合范围搜索,因此它可能满足您的查询

需要将GUID用作主键。我这样想对吗

ProductID UNIQUEIDENTIFIER NOT NULL 
ROWGUIDCOL DEFAULT (NEWSEQUNTIALID()) PRIMARY KEY CLUSTERED 
将为where子句提供最快的select

productid(guid1,guid2,…,guidn)

而且不会恶化非集群的性能

像“某物*”这样的自然键


独立选择。表只供用户查询,并从头开始以编程方式创建/重新创建。

聚集索引最适合范围搜索,因此它可能满足您的查询:

productid in ( guid1 , guid2 ,..., guidn )
但如果索引是覆盖索引,则取决于您选择的其他内容、分组依据、排序依据等。否则,优化人员可能会选择另一个非聚集索引,然后查找聚集索引。它在某种程度上还取决于该表中的行数


另外,我认为您可能希望使用NEWID()来反对NEWSEQUENTIALID()

将GUID用作聚集索引的事实肯定会对性能产生负面影响。即使使用NEWSEQUENTIALGUID,guid也不是真正顺序的——它们只是部分顺序。它们的随机性本质上肯定会导致更高的索引碎片,从而减少最佳搜索时间

此外,如果您有一个16字节的GUID作为聚集键,它将被添加到该表上的任何非聚集索引中。这听起来可能没那么糟糕,但如果你有1000万。行、10个非聚集索引,使用16字节GUID与4字节INT相比,将浪费1.2 GB的存储空间—不仅在磁盘上(这很便宜),而且在SQL server的内存中(因为SQL server总是将整个8k页加载到8k内存块中,不管它们有多满或多空)

我可以看出使用GUID作为主键的意义——它们几乎100%保证是唯一的,这对开发人员很有吸引力。但是:作为集群密钥,它们是数据库的噩梦

我的最佳实践是:如果我真的需要一个GUID作为主键,我会向表中添加一个4字节的INT标识,然后将其用作聚集键——这样效果更好

如果您有一个非集群主键,那么使用guid列表的查询速度将与使用集群主键的查询速度一样快,并且通过不对集群主键使用guid,您的表最终将执行得更好

在Kimberly Tripps的博客《索引女王》中阅读更多关于集群密钥的内容,以及为什么选择正确的密钥如此重要,并且可以比我解释得更好:


Marc

除了GUIDs不好(来自Marc_s的回答)之外,你还有一个IN子句。此喙向下延伸至:

productid = guid1 OR productid = guid2 OR ... OR productid = guidn
…在实践中,这也不是最优的


通常,
natural\u key(如'Something%')
最适合在natural key列上建立聚集索引。

in语句中不同值的不同列表并不完全是范围查询。…@marc\u s:这是一个很好的观点!但正如原始问题中提出的那样,它们是顺序GUID,因此我认为它们可能作为一个范围出现。原始序列是随机的,从Lucene.Net全文索引返回,但如果它加快了查询速度,则在内存中对GUID排序没有问题。我们是否可以说,一般来说,如果GUID是主键,则应该是非聚集的,集群化并不会给查询中的select带来任何好处。如果在我的应用程序中忽略了它,那么每次都会从头开始重新创建表,用户只需在它准备好后进行查询。对于类似的查询,我喜欢将In-csv列表拆分为一个表,然后只连接到它,这样它将使用索引。谢谢,如果我必须使用csv,我也会使用相同的想法