最近遇到一个问题,有人说表空间的自动扩展会带来碎片化,我觉得这是一个误区,有必要说说。
1.什么时候开始出现碎片化?
表空间是一个逻辑的概念,为数据库提供使用空间的逻辑结构,其对应物理结构是数据文件,一个表空间可以包含多个数据文件。
表空间存放的是段(segment)。而段是数据库一种逻辑结构,包括表段,索引段,回滚段等,段存在于表空间中,并对应一定的存储空间。
那什么时候开始出现碎片化呢?
所有的Oracle段(为了理解方便,后面把segment作为表的一个同义词)都有一个在段内容纳数据的上限,我们把这个上限称为"high water mark"或HWM。
这个HWM是一个标记,用来说明已经有多少没有使用的数据块分配给这个segment。原则上HWM只会增大,不会缩小,即使将表中的数据全部删除(delete),HWM还是为原值,由于这个特点,使HWM很象一个水库的历史最高水位,这也就是HWM的原始含义,当然不能说一个水库没水了,就说该水库的历史最高水位为0。
回过头来,当表空间中生成一个段时,将从表空间有效自由空间中为这个段的初始范围分配空间。在这些初始范围充满数据时,段会请求增加另一个范围。这样的扩展过程会一直继续下去,直到达到最大的范围值,或者在表空间中已经没有自由空间用于下一个范围。最理想的状态就是一个段的数据可被存在连续的一个范围中。这样,所有的数据存储时靠近段内其它数据,并且寻找数据可少用一些指针。但是一个段包含多个范围的情况是大量存在的,没有任何措施可以保证这些范围是相邻存储的。当要满足一个空间要求时,数据库不再合并相邻的自由范围(除非别无选择),而是寻找表空间中最大的自由范围来使用。这样将逐渐形成越来越多的离散的、分隔的、较小的自由空间,即碎片。
以上就是产生碎片化的原因。最理想的状况就是一个表初始化后所有段都是连续的,这样就不会有碎片,但是实际生产中不可能所有的表都是不变的。只要表的数据一发生变化就会存在扩展,一涉及到扩展,数据库就有可能申请到分隔开的较小的自由空间,所以说碎片化的产生和和表空间自动扩展还是手工扩展没有啥关系。如果非要保证表空间不会出现碎片化,那么就只有一种可能----数据库不会再发生变化。
2.怎么调整表空间的大小?
表空间是一种逻辑的概念,所谓调整表空间大小其实就是调整这个表空间所对应的物理上的数据文件的大小。
一个表空间可以包含多个数据文件,这些数据文件可以一部分是自动扩展的,可以一部分是不能自动扩展的。
调整表空间的手段有:
(1)添加数据文件
(2)给数据文件设置自动扩展:在块大小为8K的表空间,最大值为:32768M,换句话说,如果这个表空间的某一个数据文件的初始值是10G,那么将该数据文件设置为自动扩展后,该数据文件的最大值能达到32G,而当这个数据文件达到了32G后,如果需要扩展表空间的大小,那么仍然需要添加新的数据文件。
(3)对数据文件进行resize。这个用在2个地方:第1个是觉得初始化的数据文件过大需要收缩可以用;第2个是初始化的数据文件过小,且关闭了自动扩展,那么也可以用resize来使得数据文件变大。
3.是否需要设置表空间自动扩展呢?
个人觉得很有必要,为什么呢?当表空间被写满的时候,如果没有自动扩展的功能,那么相应的表空间就会报错夯住,数据写不进去,这个时候就会影响业务了。而Oracle自身就提供了数据文件自动扩展的功能,我们为什么不用它呢?非要自己监控然后自己再去手工resize来扩展表空间以获取更多的犯错几率?
4.自动扩展是否会影响性能?
当然会影响性能!假设初始化一个表空间只有一个数据文件且这个数据文件设置了自动扩展,这个数据文件只有10G。当表空间满了达到10G的时候,数据文件会一边扩展一边写入数据,肯定对数据库的性能有影响。
表空间能自动扩展的触发条件是什么?
(1)表空间满了
(2)对应的数据文件还有扩展的空间(8K的块大小对应的数据文件最大为32G)
如果表空间满了,而且它对应的数据文件已经扩展到最大的32G了,那么当自动扩展开始的时候,这个表空间仍然会报错,告知无法扩展。
怎么避免或者减少自动扩展带来的性能问题呢?
最不差钱的方法就是咱存储空间特别多先给表空间分配足够多足够大的数据文件;如果没有那么多存储的话,那就在初始化表空间的时候分配一定数量的数据文件,将一部分直接设置为最大的32G,另外一部分初始化为10G并让其自动扩展。剩下的就是监控表空间使用率,当表空间达到一定阈值的时候,对其添加新的数据文件。