SQL Server单列或多列主键的性能差异?

15 浏览
0 Comments

SQL Server单列或多列主键的性能差异?

如果主键是单列(例如,为每一行生成的GUID)或多列(例如,外键GUID + 偏移量),在性能方面(插入/更新和查询)是否有差异?

我认为,如果使用多列主键,查询速度应该更快,但我想插入可能会较慢,因为需要进行稍微复杂的唯一性检查。我还想象多列主键的数据类型也可能很重要(例如,如果其中一列是DateTime类型,则会增加复杂性)。这只是我用来引发答案和讨论的思考(希望如此!),并非基于事实。

我意识到有一些其他涉及此主题的问题,但我想知道的是性能影响,而不是管理/业务问题。

0
0 Comments

在SQL Server中,单列或多列主键的性能差异取决于索引和存储方式。在其他条件相同的情况下,主键的选择与性能无关,索引和其他存储选项才是决定因素。

如果数据库表被设计为具有单列主键,那么它将使用单个列来唯一标识每个记录。在这种情况下,数据库引擎将为该列创建一个聚集索引,该索引将按照主键的顺序对数据进行物理排序。这将使得通过主键进行的查找操作非常高效,因为数据库引擎可以利用索引的有序性来快速定位所需的记录。

然而,如果数据库表被设计为具有多列主键,那么它将使用多个列来唯一标识每个记录。在这种情况下,数据库引擎将为这些列创建一个复合主键索引,该索引将按照多个列的顺序对数据进行物理排序。这将导致查找操作的性能稍微下降,因为数据库引擎需要在多个列上进行比较才能找到所需的记录。

为了提高多列主键的性能,可以考虑以下解决方法:

1. 考虑使用较短的数据类型:较短的数据类型将减少存储空间和索引大小,从而提高查询性能。

2. 考虑使用自增长列作为单列主键:自增长列可以保证每个记录具有唯一的主键值,并且不需要进行额外的比较操作。

3. 考虑使用非聚集索引:如果多列主键的查询性能较差,可以考虑为其他常用查询条件创建非聚集索引,以提高查询性能。

4. 考虑使用覆盖索引:如果查询需要返回多个列的数据,可以考虑创建覆盖索引,以避免回表操作,从而提高查询性能。

单列或多列主键的性能差异取决于索引和存储方式。在设计数据库表时,应根据具体情况选择适合的主键类型,并考虑使用合适的索引和存储选项来优化查询性能。

0
0 Comments

问题的原因:单列或多列主键的性能差异主要是由于主键的组成部分是变长的和宽度较大的列,而不是主键的组成部分的数量。变长列在索引中会带来性能下降,因为每次访问都需要进行一些"解包"操作来获取数据。同时,GUID作为主键会导致非常庞大的键,而且GUID加上其他列会使键变得非常庞大。这是因为GUID通常被用于解决IDENTITY问题,而IDENTITY问题的根本原因是没有选择好的自然关系键。

解决方法:尽量保持索引列的宽度尽可能窄,只使用固定长度的非空列。避免使用GUID作为主键,尽量选择好的自然关系键。避免使用IDENTITY。

"Experience and performance tuning, not conjecture."的意思是基于经验和性能调优的实际情况,而不是猜测或推测。

"Unless MS have broken it again in the latest release (they broke Heaps in 2005)."的意思是除非微软在最新版本中再次破坏了它(他们在2005年破坏了堆),请详细说明。

在2005年之前,堆在某些操作上比良好设计的聚集索引快。然而,在2005年之后,微软的MVPs开始建议聚集索引更快。经过重新测试后发现,聚集索引的速度并没有改变,实际上微软破坏了堆,导致堆在特定操作上比聚集索引更慢。而"聚集索引更快"只是微软的市场宣传手法,用来掩盖性能下降的现实。

在这个问题中,一些人只是根据知识、书籍和文章的内容回答,而没有实际经验或测试变化。而作者则表示自己对于这个问题有实际经验,并通过实施、识别和解决问题以及进行性能测试来支持自己的观点。

感谢你的帖子,它对我很有帮助。对于记录标识问题,我决定使用int(4字节)+ char(4)作为主键字段(对于时间序列表还会添加datetime字段)。公司之前一直在所有地方使用GUID作为ID,但经过一些思考,发现它们完全过于庞大。

0
0 Comments

在SQL Server中,使用单列或多列主键可以导致性能差异。具体的性能差异取决于访问模式、读写比例以及是否将聚集索引定义在主键上。

一般来说,主键应尽可能小(32位整数),并且尽量在可能的情况下将聚集索引定义在单调递增的键上(例如自增ID),除非表中的查询中有大量的范围搜索。

如果应用程序具有较高的写入强度,并且将聚集索引定义在GUID列上,你应该注意以下几点:

1. 所有非聚集索引将包含聚集索引键,因此索引会变大。如果有许多非聚集索引,这可能会对性能产生负面影响。

2. 除非使用有序的GUID(如COMB或NEWSEQUENTIALID()),否则插入操作会导致索引随时间而碎片化。这意味着你需要定期重建索引,并可能需要增加页面中留下的空闲空间(填充因子)。

由于有许多因素会影响性能(硬件、访问模式、数据大小),建议你运行一些测试并评估你特定情况下的性能。

根据你的情况描述,你的应用程序主要是写入操作,读取操作很少,写入速度比读取速度更为关键(尽管读取速度仍然需要达到要求)。因此,对于你的情况,将主键定义为单列并将聚集索引定义在递增的键上可能更合适。

正确的主键选择和聚集索引定义取决于访问模式、读写比例和数据量等因素。建议在设计阶段通过测试和评估来确定最佳的配置。

0