2009-06-01 51 views
2

需要将GUID用作主键。难道我就在想,guid为最快查询创建主键创建GUID(guid1,guid2,guid3 ...)

ProductID UNIQUEIDENTIFIER NOT NULL 
ROWGUIDCOL DEFAULT (NEWSEQUNTIALID()) PRIMARY KEY CLUSTERED 

将给予where子句

productid in (guid1 , guid2 ,..., guidn)

最快的选择并没有恶化非群集

natural_key like 'Something*'

自主选择。用于仅由用户查询并从头开始以编程方式创建/重新创建的表。

回答

0

聚集索引是最适合于范围搜索,所以它可能满足您的查询:

productid in (guid1 , guid2 ,..., guidn) 

而是取决于你是等选择别的什么,通过分组,排序如果索引是一个覆盖指数。否则,优化程序可能会挑选另一个非聚簇索引,然后查找聚簇索引。它也在一定程度上取决于该表中的行数。

另外,我觉得你可能要使用NEWID()作为反对NEWSEQUENTIALID()

+1

IN语句中的不同值列表不完全是范围查询.... – 2009-06-01 10:01:56

+0

@marc_s:这是一个很好的观点!但它们是在原始问题中提出的顺序GUID,所以我认为它们可能会作为一个范围出现。 – 2009-06-01 10:26:11

+0

从Lucene.Net全文索引返回的原始序列是随机的,但如果它加快查询速度,在内存中对GUID进行排序没有问题。 – MicMit 2009-06-01 11:05:04

3

事实上,你正在使用GUID作为一个聚集索引肯定会产生负面的性能影响。即使使用NEWSEQUENTIALGUID,GUID也不是真正的顺序 - 它们只是部分如此。它们的随机性本质上肯定会导致更高的索引碎片化,从而导致搜索次数更少。

此外,如果您有一个16字节的GUID作为您的群集键,它将被添加到该表上的任何非聚集索引。这听起来可能不太好,但如果你有10万个。行,10个非聚簇索引,使用16字节的GUID与4字节的INT会浪费1.2 GB的存储空间 - 不仅仅在磁盘上(这很便宜),而且还在SQL服务器的内存中SQL服务器总是将整个8k页面加载到8k块内存中,无论它们有多满或空着)。

我可以看到使用GUID作为主键 - 他们几乎100%保证独一无二,这对开发人员很有吸引力。但是:作为一个集群密钥,它们对于你的数据库来说是一场噩梦。我最好的做法是:如果我确实需要一个GUID作为主键,那么我会在表中添加一个4字节的INT IDENTITY,然后将其作为聚簇键 - 结果会更好!

如果您有一个非集群主键,那么使用GUID列表的查询将与集群主键的位置一样快,并且通过不为集群键使用GUID,您的表的性能会更好到底。

了解更多的关于聚集键以及为什么它如此重要,选择一个正确的金伯利特里普斯的博客 - 索引的女王和可以解释比我做的事情要好得多:

马克

1

除了GUID不好(来自marc_s的回答),还有一个IN子句。这啄到:

productid = guid1 OR productid = guid2 OR ... OR productid = guidn 

......在实践中,这也不是最优的。

通常情况下,natural_key like 'Something%'对于您的天然密钥列中的聚集索引来说很可能会更好。