我意识到这个问题之前很可能已经被问过了,但是我在StackOverflow上搜索了一些问题,我没有真正找到答案,所以这里有。如果您发现重复,请链接到它。
出于某种原因,我更喜欢在我的主键字段中使用Guid
s(Ms {uniqueidentifier
),但我真的不知道为什么会更好。在许多教程中,我最近走了一段时间,使用了自动递增的int
。我可以看到两者的专业和缺点:
Guid
总是具有相同的大小和长度,并且没有理由担心用完它们,而在你用完之前你可以拥有多少记录是有限的。适合int
。int
是(至少在C#中)可以为空的类型,在查询数据时会打开几个快捷方式。int
更容易阅读。所以,就像标题所说的那样简单:数据库中ID(主键)列的推荐数据类型是什么?
编辑:在收到几个简短回答后,我还必须添加这个后续问题。没有它,你的答案既不引人注目也不教育......;)为什么你这么认为,另一种选择的缺点是什么让你不选择呢?
答案 0 :(得分:8)
任何足以存储预期数据范围的整数类型。对于具有大量行或更改的表,通常将32位整数视为太小(正确或错误)。一个64位的int就足够了。许多数据库不会或不会使用该整数类型,但会使用具有指定比例和精度的NUMBER类型。 10-15位是一个相当常见的大小。
选择整数类型的原因有两个:
整数的大小为:
将它与GUID(128位或普通字符串)进行比较,每个字符至少有一个字节(某些字符编码更多)加上可能只有一个字节的开销(终止)在某些情况下可能会更多。
对整数进行排序是微不足道的,假设它们是唯一的并且范围足够小,实际上可以在O(n)时间内完成,相比之下,最好是O(n log n)。
同样重要的是,大多数数据库都可以通过自动增量列和/或序列生成唯一ID。实际上,保证应用程序的唯一性非常困难,并且往往会导致密钥泛滥。
Plus自动生成的整数键通常是松散或绝对有序的(取决于数据库和配置),这是一种有用的质量。随机生成的GUID基本上是无序的,这远没那么有用。
答案 1 :(得分:6)
热门数据库现在允许更大的自动增量字段多年,所以它不是一个问题。
至于使用什么,它总是一个选择。一个不是明显更好而不是另一个,它们具有不同的特征,并且在不同的场景中各自都很好。我随着时间的推移使用了这两种模式,而我使用的下一个模式我会考虑两者。
GUID的优点:
自我增量的优点:
答案 2 :(得分:5)
使用GUID密钥的一大缺点是难以手动执行“临时”查询。有时你可以这样做非常有用:
SELECT * FROM User,其中UserID = 452245
使用GUID键可能会非常烦人。
我推荐64位整数
答案 3 :(得分:2)
告诉我您认为重要的标准。
必需在表格中是唯一的。
GUID是全局概率唯一标识符。它也很大。如果您希望您的索引在epsilon中对于Universe中的每个其他数据库安装都是唯一的,那么它是一个不错的选择。否则,它会不必要地占用大量空间。
自动增量数是好的;它很小,并且肯定在表中是独一无二的。另一方面,它无法防止重复;除了幻数之外,两个条目相同,很容易创建。
使用与正在描述的实体相关联的某些值可以避免这种情况,但是您遇到了处理唯一性的问题。
答案 4 :(得分:1)
如果你使用long,你可以创建超过1000秒,而不是用完2900万年的主键。
其他人已经提到了使用整数类型而不是UUID / GUID的一些优点。其中一大优势是指标的速度和紧凑性。
我最近参与了数据库设计的应用程序,我需要UUID,但不想放弃使用longs作为主键的优点,所以我有一个映射每个主键的“allIds”表将系统中的密钥输入到UUID。我的所有主键都是从一个序列生成的,所以它们在所有表中都是唯一的。
答案 5 :(得分:0)
如果数据库是分布式的,您可以从其他数据库获取记录,则主键在所有数据库中的表中必须是唯一的。 GUID解决了这个问题,尽管是以空间为代价。自动增量和命名空间的组合将是一个很好的权衡。
如果数据库可以为带有“前缀”的自动增量提供内部支持,那将是很好的。因此,在一个数据库中,我获得了像X1,X2,X3 ......等ID,而在另一个数据库中,它可能是Y1,Y2,Y3 ......等等。
答案 6 :(得分:0)
我问了一个类似的问题,其中有一些答案可能有所帮助。复制似乎是使用GUID的最大优势。
Reasons not to use an auto-incrementing number for a primary key
答案 7 :(得分:0)
按照Cletus的建议, 另外需要注意的是它在很大程度上取决于你的行为。永远不要使用GUID。 GUID有一大堆缺点,只有一两个上行空间。
答案 8 :(得分:0)
我从不喜欢整数和增量标识符。当您要跨不同的表(两个表具有相同的ID)或跨不同的数据库复制数据时,就会出现问题。 Guid作为字符串代表很有用,当您在Web应用程序的URL中包含id时,它也会出现问题。因此,我决定使用Guid的短字符串版本,该版本在db中类似于varchar(16)。参见下面的代码(方法WebHash()):
public static class IdentifyGenerator
{
private static object objLock = new object();
private static char[] sybmols = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z',
};
/// <summary>
/// Creates a new Unique Identity HashCode (length 16 chars)
/// </summary>
/// <returns></returns>
public static string WebHash(Guid fromGuid = default(Guid))
{
lock (objLock)
return RandomString(16, (fromGuid != default(Guid) ? fromGuid.ToByteArray() : null));
}
public static string RandomString(int length, byte[] customBytes = null)
{
Stack<byte> bytes = customBytes != null ? new Stack<byte>(customBytes) : new Stack<byte>();
string output = string.Empty;
for (int i = 0; i < length; i++)
{
if (bytes.Count == 0)
bytes = new Stack<byte>(Guid.NewGuid().ToByteArray());
byte pop = bytes.Pop();
output += sybmols[pop % sybmols.Length];
}
return output;
}
}
唯一的缺点是在SQL中创建新行时。因此,您必须创建一个类似的sql函数。
很高兴在我的地址中收到任何批评者。