请问在处理代码中的父子对象ID时,是否有最佳编码实践?数据库记录使用自动递增的整数作为ID(在初始保存时)。当然,在代码中,您无法猜测这个ID可能是什么,因此必须将其留空,并预计在事务中保存所有这些项,在获取父ID后将其设置在所有子项上然后再保存它们。
另一方面,Guids在代码中更容易处理,因为您可以愉快地先生成Id并将其设置在所有内容上,然后无需担心保存。
是否有一种好的简单方法来使用自动增量整数作为它们的数据库键来处理代码中的对象?
谢谢
请问在处理代码中的父子对象ID时,是否有最佳编码实践?数据库记录使用自动递增的整数作为ID(在初始保存时)。当然,在代码中,您无法猜测这个ID可能是什么,因此必须将其留空,并预计在事务中保存所有这些项,在获取父ID后将其设置在所有子项上然后再保存它们。
另一方面,Guids在代码中更容易处理,因为您可以愉快地先生成Id并将其设置在所有内容上,然后无需担心保存。
是否有一种好的简单方法来使用自动增量整数作为它们的数据库键来处理代码中的对象?
谢谢
GUID(全局唯一标识符)可能会成为你的主键的自然选择,如果你非要这样做,你可能会争辩说将其用作表的PRIMARY KEY。但是我强烈建议不要将GUID列用作聚集键,因为SQL Server默认情况下会这样做,除非您明确告诉它不要这样做。
你需要分开两个问题:
1) 主键是一个逻辑构造 - 可以是任何东西,真正唯一可靠地标识表中每行数据的候选键 - 一个INT,一个GUID,一个字符串 - 选择对于您的场景最有意义的。
2) 聚集键(定义表上“聚集索引”的列)- 这是一个物理存储相关的事情,在这里,稳定、增长缓慢的数据类型是最好的选择 - INT或BIGINT作为默认选项。
默认情况下,SQL Server表上的主键也用作聚集键 - 但这并不一定如此!我曾经亲眼看到分离先前基于GUID的主/聚集键带来的巨大性能提升 - 将主(逻辑)键放在GUID上,将聚集(排序)键放在单独的INT IDENTITY(1,1)列上。
正如索引女王Kimberly Tripp和其他人多次强调的那样,将GUID用作聚集键并不是最优的选择,因为由于其随机性,它会导致大量页面和索引碎片以及通常的性能问题。
是的,我知道 - SQL Server 2005及更高版本中有newsequentialid()
- 但即使这样也不完全顺序,因此也会遇到与GUID相同的问题 - 只是稍微不太明显。
还有一个问题需要考虑:表上的聚集键也将添加到每个非聚集索引上的每个条目中,因此您确实希望尽可能使它小。通常情况下,拥有20亿行的INT类型对于绝大多数表来说应该足够了 - 相比作为聚集键的GUID,您可以在磁盘和服务器内存上节省数百兆字节的存储空间。
快速计算 - 使用INT与GUID作为主键和聚集键:
总计:25 MB vs 106 MB - 这仅仅是在单个表上!
值得思考的更多内容 - 由Kimberly Tripp提供的优秀文章 - 读它,再读一遍,理解它!这是SQL Server索引的真谛。
同时: 从C# / .NET的角度来看 - 它取决于您如何访问SQL Server数据库。如果您使用像Linq-to-SQL或Entity Framework v4这样的东西,您的.NET对象将自动更新插入的ID (从您的INT IDENTITY
列) - 您根本不需要做任何事情。因此对我来说,这是您无需使用GUID的一个更少的原因.... GUID作为SQL Server集群键非常糟糕 - 不仅糟糕 - 真的、真正、非常糟糕。
INT
大四倍,因此会膨胀您的表格(如果您有大量行和几个NC索引)。另外:大多数情况下,程序员选择GUID,因为这些可以在插入数据库之前在客户端上生成 - 而这些绝对不是连续的! - marc_s