Sql server 数据库:表开头的主键列

Sql server 数据库:表开头的主键列,sql-server,oracle,db2,Sql Server,Oracle,Db2,将所有主键列放在表的开头是否会产生影响 我知道部分索引读取很可能涉及表扫描,将整行带到缓冲池中进行谓词匹配。我很想知道,主键位于表的顶部会带来什么性能提升 至少在SQL Server中,基于表中列的顺序(主键与否)没有性能优势。将主键列放在列表顶部的唯一好处是组织性。有点像有一个包含以下列的表:Id、FirstName、LastName、Address1、Address2、City、State、Zip。按照这个顺序要比地址2、州、名、Id、地址1、姓、邮编、城市容易得多。我对Oracle或DB2

将所有主键列放在表的开头是否会产生影响


我知道部分索引读取很可能涉及表扫描,将整行带到缓冲池中进行谓词匹配。我很想知道,主键位于表的顶部会带来什么性能提升

至少在SQL Server中,基于表中列的顺序(主键与否)没有性能优势。将主键列放在列表顶部的唯一好处是组织性。有点像有一个包含以下列的表:Id、FirstName、LastName、Address1、Address2、City、State、Zip。按照这个顺序要比地址2、州、名、Id、地址1、姓、邮编、城市容易得多。我对Oracle或DB2了解不多,但我相信它们是一样的。

至少在SQL Server中,基于表中列的顺序(主键与否)没有性能优势。将主键列放在列表顶部的唯一好处是组织性。有点像有一个包含以下列的表:Id、FirstName、LastName、Address1、Address2、City、State、Zip。按照这个顺序要比地址2、州、名、Id、地址1、姓、邮编、城市容易得多。我对Oracle或DB2了解不多,但我相信它们是一样的。

在Oracle中,表的列顺序通常对性能影响不大

原因是,行的所有列通常包含在单个块中,与查找/读取块相比,查找块中行的第一列和最后一列之间的时间差非常小

此外,当到达数据库块读取行时,主键可能不是最重要的列

以下是一些列顺序可能会产生影响的例外情况:

当您的表中有>255列时,行将被拆分为两个或更多块。访问前255列可能比访问其余列便宜。 如果行的最后一列为空,则占用0字节的空间。因此,如果可能,包含许多空值的列最好保留在行的末尾,以减少空间使用,从而减少IO。一般来说,由于其他空列每个占用1字节,因此节省的空间很小,因此影响很小。 启用压缩时,压缩效率可能取决于列顺序。一个很好的经验法则是,应该对具有少数不同值的列进行分组,以提高它们被压缩算法合并的可能性。 在使用IOT时,应该考虑列的顺序。使用此条款,在确定的分隔列之后的所有列都将被存储在行外,访问它们将产生额外的成本。主键始终物理存储在IOT中行的开头。 在Oracle中,表的列顺序通常对性能影响不大

原因是,行的所有列通常包含在单个块中,与查找/读取块相比,查找块中行的第一列和最后一列之间的时间差非常小

此外,当到达数据库块读取行时,主键可能不是最重要的列

以下是一些列顺序可能会产生影响的例外情况:

当您的表中有>255列时,行将被拆分为两个或更多块。访问前255列可能比访问其余列便宜。 如果行的最后一列为空,则占用0字节的空间。因此,如果可能,包含许多空值的列最好保留在行的末尾,以减少空间使用,从而减少IO。一般来说,由于其他空列每个占用1字节,因此节省的空间很小,因此影响很小。 启用压缩时,压缩效率可能取决于列顺序。一个很好的经验法则是,应该对具有少数不同值的列进行分组,以提高它们被压缩算法合并的可能性。 在使用IOT时,应该考虑列的顺序。使用此条款,在确定的分隔列之后的所有列都将被存储在行外,访问它们将产生额外的成本。主键始终物理存储在IOT中行的开头。
在DB2中,我认为关于其他数据库管理器系统的答案应该检查答案,修改较少的列应该位于每行的开头,因为在执行更新时,需要从第一个修改的列到行的末尾,才能将其写入事务日志

它只影响更新操作,插入、删除或选择不会出现问题。其影响是IO i 这稍微减少了一点,因为如果只需要写最后一列,那么应该写的信息就更少了。当在具有大量记录的大行的表上的几个小列上执行更新时,这可能很重要。如果修改了第一列,DB2将写入整行


排序列以最小化更新日志记录:

在DB2中,我认为关于其他数据库管理器系统的答案应该检查答案修改较少的列应该在每行的开头,因为执行更新时,它从第一个修改的列一直到行的末尾,将其写入事务日志

它只影响更新操作,插入、删除或选择不会出现问题。其影响是IO稍微减少了,因为如果只需要写最后一列,那么应该写的信息就更少了。当在具有大量记录的大行的表上的几个小列上执行更新时,这可能很重要。如果修改了第一列,DB2将写入整行

排序列以最小化更新日志记录:

for ORACLE 公平地说,任何和所有主键列(即使只有1个)都应该是一行中的第一列或前几列中的第一列。此外,将它们标记在行的末尾是不好的做法,尤其是在一系列可能/可能为空的属性字段之后

因此,一行如下所示:

pkcols,att1,att2,att3,VARCHAR2200

由于上述所有原因,比

附件1,附件2,附件3,瓦查尔22000,pkcols

我为什么要问?好的,不要判断,但是我们正在简化一些表的PK,开发人员已经很高兴地将新的GUID PK don'judge 2标记到行的末尾。我对此感到困扰,但需要一些反馈来证明我的担心。这对SQL Server也很重要吗?

对于ORACLE 公平地说,任何和所有主键列(即使只有1个)都应该是一行中的第一列或前几列中的第一列。此外,将它们标记在行的末尾是不好的做法,尤其是在一系列可能/可能为空的属性字段之后

因此,一行如下所示:

pkcols,att1,att2,att3,VARCHAR2200

由于上述所有原因,比

附件1,附件2,附件3,瓦查尔22000,pkcols


我为什么要问?好的,不要判断,但是我们正在简化一些表的PK,开发人员已经很高兴地将新的GUID PK don'judge 2标记到行的末尾。我对此感到困扰,但需要一些反馈来证明我的担心。这对SQL Server也很重要吗?

实际上,如果在末尾放置一个非空列(如pk),所有可空列都将分配其空间。此行为显示为varchar2,而不是number。我不知道其他类型。@Plouf-这假定RDBMS没有在实际存储中对列进行重新排序,而不是在定义中对列进行重新排序,以便首先显示所有非空列-这是一个微不足道的优化。现在,知道将哪个可为null的列放在第一位是很重要的,根据哪些列最常被填充…@Clockwork Muse Yep,但Oracle并没有做这个琐碎的优化,所以我认为值得一提@plouf你的SQLFiddle出了点问题,看,我不确定你想证明什么。此外,这种琐碎的优化1可能有害于我列出的所有原因压缩、易于访问完整扫描等,2的影响很小,因此无论如何都无关紧要,这就是Oracle不重新排序列的原因。VARCHAR2也是可变长度的,Oracle只分配所需的空间,永远不会更多。@VincentMalgrat好吧,我很困惑。我可能需要检查一些事情。实际上,如果你在末尾放一个非空的列,比如pk,所有可空的列都会被分配空间。此行为显示为varchar2,而不是number。我不知道其他类型。@Plouf-这假定RDBMS没有在实际存储中对列进行重新排序,而不是在定义中对列进行重新排序,以便首先显示所有非空列-这是一个微不足道的优化。现在,知道将哪个可为null的列放在第一位是很重要的,根据哪些列最常被填充…@Clockwork Muse Yep,但Oracle并没有做这个琐碎的优化,所以我认为值得一提@plouf你的SQLFiddle出了点问题,看,我不确定你想证明什么。此外,这种琐碎的优化1可能有害于我列出的所有原因压缩、易于访问完整扫描等,2的影响很小,因此无论如何都无关紧要,这就是Oracle不重新排序列的原因。VARCHAR2也是可变长度的,Oracle只分配所需的空间,永远不会更多。@VincentMalgrat好吧,我很困惑。我可能得再查几件事。