HTML5技术

服务的扩展性 - loveis715(5)

字号+ 作者:H5之家 来源:博客园 2016-01-04 09:43 我要评论( )

那么如何将数据库的扩展性分割为子问题呢?在决定一个数据库应该拥有哪些特性时,常常用来作为评判标准的就是CAP理论。该理论指出我们很难保证数据库的一致性(Consistency),可用性(Availability)以及分区容错

  那么如何将数据库的扩展性分割为子问题呢?在决定一个数据库应该拥有哪些特性时,常常用来作为评判标准的就是CAP理论。该理论指出我们很难保证数据库的一致性(Consistency),可用性(Availability)以及分区容错性(Partition tolerance):

  因此一系列数据库都选择了其中的两个特性来作为其实现的重点。例如常见的关系型数据库主要保证的是数据的一致性及数据的可用性,而并不强调对扩展性非常重要的分区容错性。这也便是数据库的横向扩展成为业界难题的一个原因。

  当然,如果您的应用对一致性或可用性的要求并不是那么高,那么您就可以选择将分区容错性作为重点的数据库。这些类型的数据库有很多。例如现在非常流行的NoSQL数据库大多都将分区容错性作为一个实现重点。

  因此在本节中,我们将会以关系型数据库作为重点进行讲解。又由于对关系型数据库进行横向扩展常常较纵向扩展更为困难,因此我们将首先讲解如何对关系型数据库进行横向扩展。

  首先,最为常见也最为简单的纵向扩展方法就是增加关系型数据库所在服务实例的性能。我们知道,数据库在运行时会将其所包含的数据加载在内存之中,而且最常访问的数据是否存在于内存之中是数据库是否运行良好的关键。如果数据库所在的服务实例能够根据实际负载提供足够的内存,以承载所有最常被访问的数据,那么数据库的性能将得到充分地发挥。因此在执行纵向扩展的第一步就是要检查您的数据库所在的服务实例是否拥有足够的资源。

  当然,仅仅从硬件入手是不够的。在前面的章节中已经介绍过,纵向扩展需要从两个方面入手:硬件的增强,以及软件的优化。就数据库本身而言,其最重要的保证运行性能的组成就是索引。在当代的各个数据库中,索引主要分为聚簇索引以及非聚簇索引两种。这两种索引能够加速对具有特定特征的数据的查找:

  因此在数据库优化过程中,索引可以说是最为重要的一环。从上图中可以看出,如果一个查找能够通过索引来完成,而不是通过逐个查找数据库中所拥有的记录来进行,那么整个查找只需要分析组成索引的几个节点,而不是遍历数据库所拥有的成千上万条记录。这将会大大地提高数据库的运行性能。

  但是如果索引没有存在于内存中,那么数据库就需要从硬盘中将它们读取到内存中再进行操作。这明显是一个非常慢的操作。因此为了您的索引能够正常工作,您首先要保证数据库运行所在的服务实例拥有足够的内存。

  除了保证拥有足够的内存之外,我们还需要保证数据库的索引自身没有过多的浪费内存。一个最常见的索引浪费内存的情况就是Index Fragmentation。也就是说,在经过一系列添加,更新和删除之后,数据库中的数据在存储中的物理结构中将变得不再规律。这主要分为两种:Internal Fragmentation,即物理结构中可能存在着大量空白;External Fragmentation,即这些数据在物理结构中并不是有序排列的。Internal Fragmentation意味着索引所包含节点的增加。这一方面导致我们需要更大的空间来存储索引,从而占用更多的内存,另一方面也会让数据寻找所需要遍历的节点数量增加,从而导致系统性能的下降。而External Fragmentation则意味着从磁盘顺序读取这些数据时需要硬盘重新进行寻址等操作,也会显著降低系统的执行性能。还有一个需要考虑的有关External Fragmentation的问题则是是否我们的服务与其它服务使用了共享磁盘。如果是,那么其它服务对于磁盘的使用会导致External Fragmentation的问题无法从根本上解决,巡道操作将常常发生。

  另外一个常用的对索引进行优化的方法就是在非聚簇索引中通过INCLUDE子句包含特定列,以加快某些请求语句的执行速度。我们知道,聚簇索引和非聚簇索引的差别主要就存在于是否包含数据。如果从聚簇索引中执行数据的查找,那么在找到对应的节点之后,我们就已经可以从该节点中得到需要查找的数据。而如果我们的查找是在非聚簇索引中进行的,那么我们得到的则是目标数据所在的位置。为了找到真正的数据,我们还需要进行一次寻址操作。而在通过INCLUDE子句包含了所需要数据的情况下,我们就可以避免这次寻址,进而提高了查找的性能。

  但是需要注意的是,索引是数据库在其本身所拥有的数据之外额外创建的数据结构,因此其实际上也需要占用内存。在插入及删除数据的时候,数据库同样需要维护这些索引,以保证索引和实际数据的一致性,因此其会导致数据库插入及删除操作性能的下降。

  还有一个需要考虑的则是通过正确地设置Fill Factor来尽量避免Page Split。在常见的数据库中,数据是记录在具有固定大小的页中。当我们需要插入一条数据的时候,目标页中的可用空间可能已经不足以再添加一条新的数据。此时数据库会添加一个新的页,并将数据从一个页分到这两个页中。在该过程中,数据库不仅仅要添加及修改数据页本身,更需要对IAM等页进行更改,因此是一个较为消耗资源的操作。FillFactor是一个用来控制在叶页创建时每页所填充的百分比的全局设置。在设置了FillFactor的基础之上,用户还可以设置PAD_INDEX选项,来控制非叶页也使用FillFactor来控制数据的填充。一个较高的FillFactor会使数据更加集中,由此拥有更高的读取性能。而一个较低的FillFactor则对写入较为友好,因为其防止了Page Split。

  除了上面所述的各种方法之外,您还可以通过其它一系列数据库功能来提高性能。这其中最重要的当然是各个数据库所提供的执行计划(Execution Plan)。通过执行计划,您可以看到您正在执行的请求是如何被数据库执行的:

  由于如何提高单个数据库的性能是一个庞大的话题,而我们的文章主要集中在如何提高扩展性,因此我们在这里不再对如何提高数据库的执行性能进行详细的介绍。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • net.sz.framework 框架 登录服务器架构 单服2 万 TPS(QPS) - 失足程序员

    net.sz.framework 框架 登录服务器架构 单服2 万 TPS(QPS) - 失足

    2017-04-13 11:05

  • 面向个人的技术咨询服务 - 思想瞭望者

    面向个人的技术咨询服务 - 思想瞭望者

    2017-04-05 12:07

  • net.sz.framework 框架 轻松搭建服务---让你更专注逻辑功能---初探 - 失足程序员

    net.sz.framework 框架 轻松搭建服务---让你更专注逻辑功能---初探 -

    2017-04-02 10:11

  • 微服务--webapi实现,脱离iis,脱离tomcat - 失足程序员

    微服务--webapi实现,脱离iis,脱离tomcat - 失足程序员

    2017-03-30 11:00

网友点评
/