我有一个应用程序,在几乎所有的表中使用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是完全可以的。