我有一个应用程序,在几乎所有的表中使用GUID作为主键,我读到使用GUID作为主键时存在性能问题。老实说,我还没有看到任何问题,但我要开始一个新的应用程序,我仍然想使用GUID为主键,但我在考虑使用一个复合主键(GUID和可能另一个字段)。

我之所以使用GUID,是因为当你有不同的环境,如“生产”、“测试”和“开发”数据库时,它们很好且易于管理,而且还用于在数据库之间迁移数据。

我将使用实体框架4.3,我想在应用程序代码中分配Guid,然后将其插入数据库。(例如,我不想让SQL生成Guid)。

为了避免与此方法相关的性能损失,创建基于gui的主键的最佳实践是什么?


当前回答

好吧,如果您的数据从来没有达到数百万行,那就没问题了。如果你问我,我从来不使用GUID作为任何类型的数据库标识列,包括PK,即使你强迫我用霰弹枪在头上设计。

使用GUID作为主键是一个决定性的缩放停止器,而且是一个关键的。 我建议您检查数据库标识和序列选项。序列是独立于表的,可以为您的需求提供解决方案(MS SQL有序列)。

如果你的表最多达到几千万行,例如5000万行,你将无法在可接受的时间读/写信息,甚至标准的数据库索引维护也将变得不可能。

然后您需要使用分区,并且可扩展到5亿甚至1- 20亿行。添加分区的方式不是最简单的事情,所有读/写语句必须包括分区列(完整的应用程序更改!)

这些数字(5000万和5亿)当然是为轻选择使用。如果您需要以复杂的方式选择信息和/或有大量的插入/更新/删除,对于一个非常苛刻的系统,这些甚至可能是1-2百万和5千万。如果您还添加了完整恢复模型、高可用性和无维护窗口等现代系统常见的因素,情况就会变得非常糟糕。

注意,在这一点上,20亿是int的限制,看起来很糟糕,但int是4倍小,是一个顺序类型的数据,小的大小和顺序类型是数据库可伸缩性的首要因素。你可以使用big int,它只小了两倍,但仍然是顺序的,顺序是非常重要的,甚至比大小更重要,当涉及到数百万或数十亿行的时候。

如果GUID也是聚集的,情况就更糟了。插入一个新行实际上会随机存储在物理位置的任何位置。

即使只是一个列,不是PK或PK部分,只是索引它是麻烦的。从碎片化的角度来看。

有一个guid列是完全可以的,就像任何varchar列一样,只要你不使用它作为PK部分,通常作为连接表的键列。您的数据库必须有自己的PK元素,使用它们过滤和连接数据-过滤后也通过GUID是完全可以的。

其他回答

我目前正在用EF Core开发一个web应用程序,下面是我使用的模式:

我所有的类(表)都有一个int PK和FK。 然后,我有一个类型为Guid的附加列(由c#构造函数生成),列上有一个非聚集索引。

EF中所有表的连接都是通过int键管理的,而所有来自外部(控制器)的访问都是通过guid完成的。

这个解决方案允许在url上不显示int键,但保持模型整洁和快速。

大多数情况下,它不应该用作表的主键,因为它确实会影响数据库的性能。 关于GUID对性能的影响和作为主键的有用链接。

https://www.sqlskills.com/blogs/kimberly/disk-space-is-cheap/ https://www.sqlskills.com/blogs/kimberly/guids-as-primary-keys-andor-the-clustering-key/

好吧,如果您的数据从来没有达到数百万行,那就没问题了。如果你问我,我从来不使用GUID作为任何类型的数据库标识列,包括PK,即使你强迫我用霰弹枪在头上设计。

使用GUID作为主键是一个决定性的缩放停止器,而且是一个关键的。 我建议您检查数据库标识和序列选项。序列是独立于表的,可以为您的需求提供解决方案(MS SQL有序列)。

如果你的表最多达到几千万行,例如5000万行,你将无法在可接受的时间读/写信息,甚至标准的数据库索引维护也将变得不可能。

然后您需要使用分区,并且可扩展到5亿甚至1- 20亿行。添加分区的方式不是最简单的事情,所有读/写语句必须包括分区列(完整的应用程序更改!)

这些数字(5000万和5亿)当然是为轻选择使用。如果您需要以复杂的方式选择信息和/或有大量的插入/更新/删除,对于一个非常苛刻的系统,这些甚至可能是1-2百万和5千万。如果您还添加了完整恢复模型、高可用性和无维护窗口等现代系统常见的因素,情况就会变得非常糟糕。

注意,在这一点上,20亿是int的限制,看起来很糟糕,但int是4倍小,是一个顺序类型的数据,小的大小和顺序类型是数据库可伸缩性的首要因素。你可以使用big int,它只小了两倍,但仍然是顺序的,顺序是非常重要的,甚至比大小更重要,当涉及到数百万或数十亿行的时候。

如果GUID也是聚集的,情况就更糟了。插入一个新行实际上会随机存储在物理位置的任何位置。

即使只是一个列,不是PK或PK部分,只是索引它是麻烦的。从碎片化的角度来看。

有一个guid列是完全可以的,就像任何varchar列一样,只要你不使用它作为PK部分,通常作为连接表的键列。您的数据库必须有自己的PK元素,使用它们过滤和连接数据-过滤后也通过GUID是完全可以的。

不要在用户界面中公开Id的另一个原因是,竞争对手可以看到您的Id在一天或其他时间段内的增量,从而推断出您正在做的业务量。

This link says it better than I could and helped in my decision making. I usually opt for an int as a primary key, unless I have a specific need not to and I also let SQL server auto-generate/maintain this field unless I have some specific reason not to. In reality, performance concerns need to be determined based on your specific app. There are many factors at play here including but not limited to expected db size, proper indexing, efficient querying, and more. Although people may disagree, I think in many scenarios you will not notice a difference with either option and you should choose what is more appropriate for your app and what allows you to develop easier, quicker, and more effectively (If you never complete the app what difference does the rest make :).

https://web.archive.org/web/20120812080710/http://databases.aspfaq.com/database/what-should-i-choose-for-my-primary-key.html

附注:我不确定你为什么要使用复合PK,或者你认为这会给你带来什么好处。