热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

SQLServer中的页如何影响数据库性能(转)

无论是哪一个数据库,如果要对数据库的性能进行优化,那么必须要了解数据库内部的存储结构。否则的话,很多数据库的优化工作无法展开。对于对于数据库管理员来说,虽然学习数据库的内存存储结构比较单调,但是却是我们必须攻下的一个堡垒。在SQLServer数据库

无论是哪一个数据库,如果要对数据库的性能进行优化,那么必须要了解数据库内部的存储结构。否则的话,很多数据库的优化工作无法展开。对于对于数据库管理员来说,虽然学习数据库的内存存储结构比较单调,但是却是我们必须攻下的一个堡垒。在SQLServer数据库

无论是哪一个数据库,如果要对数据库的性能进行优化,那么必须要了解数据库内部的存储结构。否则的话,很多数据库的优化工作无法展开。对于对于数据库管理员来说,虽然学习数据库的内存存储结构比较单调,但是却是我们必须攻下的一个堡垒。在SQLServer数据库中,数据页是其存储的最基本单位。系统无论是在保存数据还是在读取数据的时候,都是以页为单位来进行操作的。

  

  一、数据页的基本组成。

  如上图所示,是SQLServer数据库中页的主要组成部分。从这个图中可以看出,一个数据页基本上包括三部分内容,分别为标头、数据行和行偏移量。其中数据行存储的是数据本身,其他的标头与偏移量都是一些辅助的内容。对于这个数据页来说,笔者认为数据库管理员必须要了解如下的内容。

  一是要了解数据页的大小。在SQLServer数据库中数据页的大小基本上是固定的,即每个数据页的大小都为8KB,8192个字节。其中每页开头都有一个标头,其占据了96个字节,用于存储有关页的信息。如这个页被分配到页码、页的类型、页的可用空间以及拥有这个页的对象的分配单元ID等等信息。不过值得庆幸的是,这些内容数据库都会自动管理与更新,不需要数据库管理员担心。数据库管理员只需要知道的是,这个数据页中最多可以用来保存数据的空间。每个页的大小是8192个字节,扣除掉一些必要的开销(如标头信息或者偏移量所占用的空间),一般其可以用来实际存储数据的空间只有8000字节左右。牢记这个数字,对于后续数据库性能的优化具有很大的作用。详细的内容笔者在后续行溢出的部分会进行说明。

  二是需要注意行的放置顺序。在每个数据页上,数据行紧接着标头按顺序放置。在页的末尾有一张行偏移表。对于页中的每一行,每个行偏移表都包含有一个条目。即如果业中的数据行达到100条的话,则在这个行偏移表中就对英100个条目。每个条目记录中记录对应行的第一个字节与页首的距离。如第二个跳就记录着第二个数据行的行首字母到数据页页首的位置。由于每个数据行的大小都是不同的,为此这个行偏移表中记录的内容也是没有规律的。这里需要注意的是,行偏移表中的条目顺序与页中行的顺序是相反的。这主要是为了更方便数据库定位数据行。

  二、大数据类型与行。

  根据SQLServer数据库定义的规则,行是不能够跨页的。如上图所示,如果一个字段的数据值非常大,其超过8000字节。此时一个页已经不能够容纳这个数据。此时数据库会如何处理呢?虽然说在SQLServer数据库中,行是不能够跨页的。但是可以将行分成两部分,分别存储在不同的行中。所以说,对于大数据类型来说,是不受到这个页大小(或者说行大小)的限制的。根据上面的分析可以看出,一个数据页其最大可以用的存储空间在8KB。如果扣掉一些必要的开销,其只有8000字节左右。当某条记录的所有列(包括固定长度的列与可变长度的列其大小超过这个限制的时候,数据库就会将其进行分行处理,分别存储在两个不同的页中。当某张表格中列的总大小超过限制的8KB(实际上还还不到一点)字节时,数据库系统会从最大长度的列开始动态的将一个或多个可变长度列移动到另外一个页中。简单的说,就是将某个列超过的部分单独存放在另一个页中。并且同时还会存储一些指针之类的信息,以便在不同页的记录中建立关联。这种现象在SQLServer数据库中给其取了一个名字,叫做行溢出。

  三、行溢出对于数据库性能的不利影响。

  掌握了上面关于数据页的基本工作原理后,数据库管理员需要重点理解行溢出对于数据库性能的不利影响。即需要了解,当所有列(包括固定长度的列与可变长度的列)的累积长度超过一个数据页(或者一个数据行)的最大承受限度时,会将列的内容分行来进行存放。数据库如此处理,对数据库的性能会有不利的影响吗?如果有的话,该如何避免?

  一般来说,每行的记录超过页的最大容量时,肯定会对数据库的性能造成不利的影响。这是毋庸置疑的。因为当超过这个容量时,数据库系统就需要对这个数据行进行分页处理。而分页处理需要数据库额外的开销。如在分页保存时,需要给数据库添加额外的指针;在查询数据的时候,由于分页情况的存在,为了读取一条完整的记录,数据库系统可能不得不读取多页的内容;当进行更新操作,将某个字段的内容变短,导致整行的内容在页的最大范围之内,则相关的记录会被保存在同一个行中。这些操作都需要数据库额外的开销。当在同一个时间处理这些作业多了,那么积累起来,对数据库性能的影响就会很显著。同理,此时如果对相关的记录进行排序、统计等操作,由于涉及到多个页,会延长这些作业的执行时间,即降低数据库的性能。

其次需要注意的是对一些变长字段的限制。在SQLServre数据库中,也含有varchar等变长的数据类型。在SQLServer数据库中对此有最大长度的限制。一般情况下,其最大长度不能够超过不能够超过8000字节的限制。不过他们的总宽度可以超过这个8KB的限制。如果单列的数据长度超过这个限制,那么就不能够使用普通的数据类型。如对于那些用来保存图片或者多媒体的数据,必须要使用大对象数据类型。因为只有这些大对象数据类型不受这个长度的限制。数据库对对于这些大型数据库类型对象有特殊的处理方法。

  四、数据库设计时的注意事项。

  在数据库运行时,如果存在比较多的行溢出现象,会在很大程度上影响数据库的性能。所以在数据库设计时,需要考虑到这种情况。一般的数据类型不会造成行溢出的情况。只有一些varchar nvarchar或者CLR用户自定义类型的列,比较容易造成这个行溢出现象。所以在设计数据库时,数据库管理员应该根据用户提供的样板数据分析可能发生行溢出现象的百分比,以及评估会发生溢出现象的频率。如果溢出现象发生的百分比或者频率比较高的话,那么数据库管理员就需要考虑对表格进行规范化处理,以提高数据库的性能,减少溢出现象对于数据库的不利影响。

  一般来说,有两种方法可以显著的降低这个行溢出现象对数据库性能的影响。一是假设列定义了varchar或者用户自定义数据类型等数据类型的时候,如果其长度比较长,很有可能引起行溢出现象的话,那么就干脆使用大对象数据类型。对于大对象数据类型SQLServer数据库会采取特殊的管理方法,会讲这个数据与普通数据分开来管理。所以可以在很大程度上降低行溢出现象对数据库性能的影响。不过需要注意的是,管理这些大对象数据类型,数据库本身就需要花费更多的精力与资源。所以采用这种方式带来的收益,与行溢出现象带来的损失就会有一个轻重之分的问题。数据库管理员要评估由此带来的收益能够弥补行溢出对象带来的损失。如果可以弥补的话,那么可以采用这个方案。如果不可以的话,那就得不偿失了。故笔者并不是很推荐使用这种方法。笔者现在采用的是下面要介绍的这种方式。

  第二种方法执行起来比较简单,具有比较强的可执行性。即如果某个表格中有varchar或则用户自定义的数据类型,而且其最大长度也比较长,很容易造成行溢出现象。此时最好将这些列与表中的其他列分开来存放。即将他们放在两张不同的表中。然后再通过join语句来进行连接。由于数据页对单个列的最大长度有限制,所以如此处理的话,就不怎么会发生行溢出的现象。此时如果需要查询完整的记录,也需要访问多个页。但是在实际工作中,往往不需要访问全部的信息。如在更新或者统计操作时,不需要更新varchar数据类型的字段,那么数据库的效率就会有很大的提升。即使需要访问完整的记录,需要访问多个页。但是采取join操作也要比行溢出操作性能来的好。如在更新数据时将varchar的列缩短了,此时由于在两个不同的表中,也不会出现合并行的问题。所以可以在很大程度上节省数据库的开销。显然,这种分表处理的方式更加简单,很容易操作。所以笔者强烈建议采用这种方式来避免行溢出对SQLServer数据库造成的不利影响。

推荐阅读
  • SQL中UPDATE SET FROM语句的使用方法及应用场景
    本文详细介绍了SQL中UPDATE SET FROM语句的使用方法,通过具体示例展示了如何利用该语句高效地更新多表关联数据。适合数据库管理员和开发人员参考。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 使用C#开发SQL Server存储过程的指南
    本文介绍如何利用C#在SQL Server中创建存储过程,涵盖背景、步骤和应用场景,旨在帮助开发者更好地理解和应用这一技术。 ... [详细]
  • 本文探讨了适用于Spring Boot应用程序的Web版SQL管理工具,这些工具不仅支持H2数据库,还能够处理MySQL和Oracle等主流数据库的表结构修改。 ... [详细]
  • 本文详细介绍了如何通过多种编程语言(如PHP、JSP)实现网站与MySQL数据库的连接,包括创建数据库、表的基本操作,以及数据的读取和写入方法。 ... [详细]
  • 在当前众多持久层框架中,MyBatis(前身为iBatis)凭借其轻量级、易用性和对SQL的直接支持,成为许多开发者的首选。本文将详细探讨MyBatis的核心概念、设计理念及其优势。 ... [详细]
  • 在使用 DataGridView 时,如果在当前单元格中输入内容但光标未移开,点击保存按钮后,输入的内容可能无法保存。只有当光标离开单元格后,才能成功保存数据。本文将探讨如何通过调用 DataGridView 的内置方法解决此问题。 ... [详细]
  • 本文详细介绍了如何在 Linux 平台上安装和配置 PostgreSQL 数据库。通过访问官方资源并遵循特定的操作步骤,用户可以在不同发行版(如 Ubuntu 和 Red Hat)上顺利完成 PostgreSQL 的安装。 ... [详细]
  • 如何在PostgreSQL中查看数据表
    本文将指导您使用pgAdmin工具连接到PostgreSQL数据库,并展示如何浏览和查找其中的数据表。通过简单的步骤,您可以轻松访问所需的表结构和数据。 ... [详细]
  • 利用存储过程构建年度日历表的详细指南
    本文将介绍如何使用SQL存储过程创建一个完整的年度日历表。通过实例演示,帮助读者掌握存储过程的应用技巧,并提供详细的代码解析和执行步骤。 ... [详细]
  • 本文介绍了如何通过 Maven 依赖引入 SQLiteJDBC 和 HikariCP 包,从而在 Java 应用中高效地连接和操作 SQLite 数据库。文章提供了详细的代码示例,并解释了每个步骤的实现细节。 ... [详细]
  • 在使用SQL Server进行动态SQL查询时,如果遇到LIKE语句无法正确返回预期结果的情况,通常是因为参数传递方式不当。本文将详细探讨这一问题,并提供解决方案及相关的技术背景。 ... [详细]
  • 本文介绍如何通过创建替代插入触发器,使对视图的插入操作能够正确更新相关的基本表。涉及的表包括:飞机(Aircraft)、员工(Employee)和认证(Certification)。 ... [详细]
  • MySQL缓存机制深度解析
    本文详细探讨了MySQL的缓存机制,包括主从复制、读写分离以及缓存同步策略等内容。通过理解这些概念和技术,读者可以更好地优化数据库性能。 ... [详细]
  • SQLite 动态创建多个表的需求在网络上有不少讨论,但很少有详细的解决方案。本文将介绍如何在 Qt 环境中使用 QString 类轻松实现 SQLite 表的动态创建,并提供详细的步骤和示例代码。 ... [详细]
author-avatar
饰间人爱642_370
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有