2016-08-11 陈龙 恩墨学院
探究 Oracle 高水位对数据库性能影响1
大家好!我是来自云和恩墨的陈龙,目前主要负责Oracle技术支持工作。在我开始学习Oracle 的时候就听eygle老师说过,要想学好技术,一定要要多做实验,多做学习记录,理论与实践相结合,才能真正理解吸收那些知识,所以今天我想分享一下对Oracle高水位线与SQL访问性能相关性的研究体会。谈不上很深入的研究,只是想与大家分享我的Oracle学习过程,希望能与大家交流进步。之所以分享这个学习内容,是因为在我曾经经历的一些优化项目中,遇到由于高水位导致SQL访问性能下降的问题,这促使我想更深入的去理解:什么是高水位线? 高水位到底会带来哪些影响? 应该怎样更好的解决高水位带来的问题?在开始深入分析之前,让我们先来了解一下高水位线HWM。
1HWM的基本原理(概念)在Oracle中,高水位线(High-warter mark, HWM)被用来形容数据块的使用位置,即说明那些块是已经被使用的,那些没有。在创建一个新的表时,Oracle 就会为这个对象分配一个段。在这个段中,第一个区的第一个块在创建时就会被分配存储一些表头信息。高水位的管理机制在MSSM和ASSM中不同,下面分别介绍这两种管理机制:手动段空间管理(MSSM)在以往的手动段空间管理中(MSSM),高水位标记HWM, 一个段分成三部分,header block,used block(row data),unused block,其中used block和unused block之间的分界线就是高水位标记HWM,当进行全表扫描的时候,会扫描到HWM下的所有数据块,即使used block中很多数据被删除了,全表扫描还是以HWM为准。当插入insert时,freelist中没有空闲块,HWM会向上移动,但是只会向上移动,不会自动收缩,即使delete大量数据,导致HWM下有很多空闲块。如下图:
第一个区的第一个块就称为段头(SEGMENT HEADE),段头中就储存了一些信息,基中HWM的信息就存储在此。此时,因为第一个区的第一块用于存储段头的一些信息,虽然没有存储任何实际的记录,但也算是被使用,此时HWM是位于第2个块当我们不断插入数据到PM_USER后,第1个块已经放不下后面新插入的数据,此时,ORACLE将高水位之上的块用于存储新增数据。
在向表里插入数据后,HWM本身也向上移.也就是说,当我们不断插入数据时,HWM会往不断上移,这样,在HWM之下的,就表示使用过的块,HWM之上的就表示已分配但从未使用过的块。
当对表进行导出,导入后,或者move等操作后,HWM就会降低到真实水平上。自动段管理(ASSM)在自动段管理(ASSM)中,利用位图来代替空闲列表,当会话向表插入数据时,数据库只格式一个单独的位图块,而不是像MSSM中那样,会预先格式化一组块。
在ASSM表空间中,除了一个HWM外,还有一个低HWM。在MSSM中,HWM推进时,所有的块都会格式化并立即生效,这样Oracle 就可以安全的读取这些块。但是对于ASSM,当HWM推进时,Oracle 并不会立即格式所有的块,只是在第一次使用的时候才会对这些块进行格式化。也就是说,在第一次使用的的时候,即进行insert 操作时,数据会插入到块中的任意水位线,位于低水位线(LHMW)和高水位线(HHMW)之间。因此在这个区域的许多块就不会被格式化。在一个ASSM段中的每个数据块可能为这些状态:◎ 在HWM之上这些块都是没有格式化,且没有被使用◎在HWM之下这些块会处于这些状态之一:• 已经分配,但是没有被格式化且没有被使用• 已经格式化且包含数据• 已经格式化,但是已经删除数据,块为空下面来了解整个过程:
如图所示,在没进行数据插入前,段中的所有数据块都是没有格式化的且没有被使用。假设这个时候某会话将数据插入时,数据库会把数据写到任何可以利用的空间块中。如下图所示:
数据库也可能会选择HWM和低HWM之间的任何数据块,或者低HWM之下的任何可用的空间的块。注意低HWM位置,因为HWM之下的块只有在被使用的时候,才进行格式化,所以当存在数据扫描时,特别是全表扫描,Oracle 会读取到低HWM的位置。如下图所示:
如果某条会话将数据插入到某表中,但是在当前的HWM之下没有足够的可用空间,那么这个时候Oracle 会推进HWM,重新分配一组新的没有格式化的块。当HWM与低HWM之间的位置被填满时,HWM会继续往前推进,而低HWM会相应的推进到旧的HWM位置中。以此类推,当数据库不断的插入数据,HWM会持续往前推移,而低HWM会尾随其后,除非重建、或缩小该对象等,否则HWM从不往回退。
2HWM 演示过程(上)原理描述完了,那么现在我们来测试一下,验证之前我们所描述的部分。我们先从MSSM管理的方式开始:
新建一个表,然后存储分配较多的对象,
插入较多的数据,
现在来查询下全表扫描所花时间,
从执行计划来看,该查询走得时全表扫描,期间产生6278个物理读,30028个逻辑读。现在来分析该表,查看统计信息,
从该表的统计信息来看,该表公有15384个块,其中没有用到的块有0个,共有1003089行。现在来测试下delete对hwm的影响,
从统计信息来看,该表使用的块还是15384个块,但是空余块依然是0个,按道理来说,在delete 后,应该会有空余的块才对。其中,这里可以看出行数已经变为了0.从这里就可以验证了之前的说法,即HWM在插入数据时,当现有空间不足而进行空间的扩展时会向上移,但删除数据时不会往下移。这就会造成RACLE的全表扫描是读取ORACLE高水位标记下的所有BLOCK,也就是说,不管HWM下的BLOCK现在实际有没有存放数据,ORACLE都会一一读取,这样,在DELETE表后,ORACLE读了大量的空块,耗去了大量的时间测试环境没有show_space 这个过程,现在声明它:
那么这个就是HWM所有的BLOCK编号。