首页 > 其他分享 >23、表空间及段区块_1(段区块管理、pctfree、数据块结构、行迁移、高水位)

23、表空间及段区块_1(段区块管理、pctfree、数据块结构、行迁移、高水位)

时间:2024-11-22 10:09:07浏览次数:1  
标签:pctfree 数据文件 及段 t1 空闲 extent 空间 区块 block

oracle数据库的物理存储结构

1、spfile:参数文件
2、controlfile:控制文件
3、datafile:数据文件
4、redo log
5、arch:归档日志

oracle数据库的datafile(数据文件)

datafile:oracle有多个数据文件

图解:
数据库的数据文件被格式化成一个一个大小相等的block(2k、4k、8k、16k、32k),一般都是8k

block(数据块)
1、数据文件被格式化成一个一个大小相等的block;
2、是IO的最小单元

表空间
表空间:一个或者多个数据文件组成的一个组;如果表空间不够了,可以向它加入数据文件;如果一个表非常大的话,一个数据文件就存储不了,就需要多个数据文件来存储,因为数据文件的大小是有限制的,所以有了一个表空间的概念,如果一个数据文件存储不了了,可以向表空间里面扩充多个数据文件


图解:
一个或者多个数据文件组成一个表空间,将来在表空间里要建一个表,这个表可能被建在不同的数据文件上(数据文件4、数据文件5或者数据文件4和数据文件5上...)

表是建在表空间上的

oracle数据库表空间的类别

1、system表空间(系统表空间):放着字典表(核心的字典表)
2、systemaux表空间(系统辅助表空间,oracle版本10g开始):放着辅助的字典表(存着历史性能信息)
3、temp表空间(临时表空间):放着临时数据
4、undo表空间:放着修改过的数据(比如:将1改为了2,就把1存到undo表空间里,避免操作失误的时候可以rollback回来,把2再改回1)

除了这些系统相关的表空间以外,我们还可以建一些别的表空间

oracle数据库支持表空间级别,block的大小不一样的情况(建议不这么做),这种情况需要在buffer cache里面有相同大小的buffer与其对应:8k的block对应8k的buffer,16k的block对应16k的buffer,32k的block对应32k的buffer

段区块

图解:
一个表空间,现在要在表空间1(tb1)上建一个表(t1),从存储的层面上来说,我们要建的表(t1)叫做表段(我们建了一个表,就是说我们建了一个段(表段));从存储的层面上来讲,一个表是一个段,一个索引是一个段;
现在要在tb1上建一个段t1,在oracle版本10g的时候,在建t1的时候,先分配几个物理上连续的块(就是一个区)(比如分了4个块);如果不分的话,一个一个的给,这时候就会出现一个问题:此时在tb1上又建了一个表t2,这时候第一个块给t1,第二个块给t2,......就会出现在一个表空间里,里面有好多表,这些表参差不齐,块之间互相交叉;将来如果对t1做全表扫描的话,只能先读第一个块,然后隔一个才能读下一个块,就会发生多次IO读;如果一次性分4个块给t1,全表扫描的时候就可以一次性读完,只发生一次IO读,基于这个,oracle提出了一个区(extent)的概念

段(segment)分为
1、表段
2、索引段

区(extent)的概念
1、物理上连续的多个块,是一个区(extent)
2、区(extent)是段分配空间的最小单位

段区块的关系
图示:

一个extent区由多个块组成,一个段由多个区组成,一个表空间有多个段,一个表空间由多个数据文件组成

段区块的管理

有两个管理:
1、区的管理(表空间的管理)
两种方式:
1、local(本地)
2、字典

2、段的管理
两种方式:
1、manual(手动)
2、auto(自动)

区(表空间)的管理

图解:
现在在表空间里面建一个表t1,首先:分配区,在表空间里面找空的extent区;t1表需要8个block,fet表的第二行记录着表空间里面的第二行有9个空的block,就把这一行的8个block给t1,之后fet表的第二行的记录还在,但是是记录着表空间里面的第二行有1个空的block,uet表里面就加上对应那一行被用的block的数量

区的管理方式(表空间的管理方式):
在表空间里面,对extent区进行空间的记录(哪些区用了,哪些还没有用)

1、字典管理方式
oracle在数据库的system表空间里面记录两张表:fet表(free extent表)、uet表(used extent表)

对于字典的管理方式,第一、需要写SQL来找空的extent;
第二、需要修改两张记录表(fet表:delete或者update,uet表:inster),还会产生redo、undo

这种方式的坏处:
1、需要8个block,一行有9个block,还剩下1个block,产生了小碎片;
2、使用SQL来访问,性能比较差
3、随着时间的推移,小碎片会越来越多,有一个进程smonitor,会将在一块的小碎片合并(由于时间的不同,相邻的block,记录的信息也不在一块,有的记录在表的前面,然后跟它相邻的block的信息因为时间的关系被记录在表的后面,就出现的虚块的现象,就是说现在需要16个block,前面记录了8个block,后面记录了8个block,就找不到一个16个block的空间),因为合并,需要把fet表全表扫描一遍,又因为随着时间的推移,小碎片越来越多,所以smonitor清理起来很麻烦,会造成smonitor会hang住的情况:
图示:

2、local本地管理方式
每一个数据文件里面有很多的extent,每一个数据文件,自己管理自己里面的extent

图解:
在每一个数据文件的头部,找出六个块来,64kbit的空间来记录extent:被分配的extent记录为1,没有被分配的extent记录为0,一个位表示一个extent(8个block),这样,要找一个空的extent(8个block),就在数据文件的头部里找,找一个0,如果要找一个16个block的extent,就找两个0的,这样的好处:
1、不需要使用SQL了,找到空的extent要分配,分配的时候,只要把0改为1就行了,不管是找空的extent,释放extent,还是修改记录,都是一些位操作了
2、要找16个block时,找两个0的就可以,也不存在虚块的现象,也不会产生小碎片,也不需要合并了

区的管理方式:建议使用local本地管理的方式

段的管理


图解:
一个表t1(8个block),分配了一个区,那么这个表怎么用这个extent里面的block?
要在t1里面做inster,插入一行数据(占800bit),第一个块:段头块,里面记录着相关段的信息,里面不能存放数据,第二个开始做inster,现在因为第二个块是空的(8k),做inster显然空间够;但是随着时间的推移,每一个块里都有好多行,当然还有就是这个extent用完了的情况;现在假设用了六个块,然后中间的块,删了一些行,然后每个block还剩一些空间,这时候对t1表做inster(1000bit),oracle的需求是:在这已经使用的六个block里面,需要一个能够容纳1000bit的block;每一个块是8k,需要1000bit,就是需要一个块大约13%的空间,所以只要剩余的空间大于13%,都可以用。

对于区(表空间)来说,段里面所有的extent用完了,需要新的extent的时候,才涉及到区(表空间)的管理;一个段被分配了很多区了,无论做inster、update、delete,只要不需要新的extent就不会涉及到区的管理;所以DML操作绝大部分不会涉及到区的管理(表空间的管理);
但是对于段来说,无论做inster、update、delete,每一次的DML操作,都会涉及到段的管理;所以如果段的管理方式选错了,对DML的影响还是很大的;

oracle怎么记录一个段已经分配给extent里面的每一个block的空间使用情况呢?两种方式:

段的管理方式:
1、manual管理方式:
pctfree(空闲百分比)
这里有一个参数:pctfree(空闲百分比)(默认是:10%)
一个block,要做inster,插入数据,oracle会尝试着在block里面尽量的留大于等于10%的一个空闲空间作为pctfree,但是也有可能小于10%,当block的空间剩余10%的时候,就说这个block满了,用的话,就要用下一个block了(也就是说,当一个块的空闲空间大于10%的时候,还有空闲空间;空闲空间小于10%的时候,就没有空闲空间了)

图解:
oracle会在段头块里面记录着一个地址,指向后面的第一个空闲空间大于10%的块的地址,第一个空闲空间大于10%的块也记录着下一个空闲空间大于10%的块的地址,以此类推;
然后在t1里面做inster,假设要插入2000bit,大约空闲空间25%,然后找空闲空间大于25%的块,段头,然后找,找到第一个有空闲空间的块,剩余80%,满足了,就用它;然后剩余55%了;
在做inster的时候,oracle会锁住t1这个表的段头块,锁住以后,遍历free list(链表),找空闲空间;
现在server process1在对t1做inster,这时候,server process2也要对t1表做inster,这时候,t1这个表的段头块已经被锁住了,就会产生free list争用,就会产生等待事件;
所以oracle就会做一件事:使用多个free list,每个链表链一部分空闲空间,减少一部分free list征用

段管理使用manual的话,就使用free list链表

使用free list(链表)来管理这些空闲空间大于10%的块,将这些空闲空间大于10%的块链起来

pctused(使用百分比)
这里有一个参数:pctused(使用百分比)

图解:
现在有一个链表,现在要做inster,插入数据,假设对第二个块做inster,inster的话,第二个块的空闲空间就小于10%了,然后把它拿下来了;然后删除一行之后,又得挂上去;拿下来,挂上去就需要锁住链,然后去修改,所以就出现一个问题:插入一行,拿下来,修改链表;删除一行,挂上去也要修改链表,所以oracle就定义了一个参数:pctused;
假设pctused = 40%,inster以后,空间剩余8%,被拿下来了;delete一行,空间剩余又变回12%了,这时候还不把它挂上去,又删了一行,剩余22%,这时候也还不把它挂上去,直到空闲空间大于等于40%才挂上去

2、auto管理方式:

图解:
oracle在前面的这些块,又拿出一部分块来,然后在下面组成新的块;这部分使用位图的方式来记录下面组成的新块,使用位的方式来记录下面的块的空间的使用情况;假设以后要在这个段里面找一个1000bit的空闲空间,只需要读位图就可以,因为在位图里面以位的方式记录着所有块的空间使用情况,计算机对位的操作是最擅长的,这里位的方式也不存在锁的概念;
假设现在要找一个1000bit的空闲空间,pctfree = 10%,block = 8k,需要大约23%的空闲空间,就找空闲空间大于等于23%的块,就满足这个需求;现在找,找到一个块剩余30%,可以满足,再找,找到一个剩余24%的块,它就用剩余24%的,因为用剩余30%的产生小碎片,用24%的刚好,然后如果有23%的,那么更好;

使用位图的方式的好处:
1、计算速度快
2、找的时候可以找到正好的,而manual方式是找到满足需求的就用,不管剩余空间有多大

段的管理方式:建议使用auto的方式

oracle数据块(block)的结构


图解:
数据块有:块的头部,从上往下记录,下面是数据行,从下往上存储数据,中间是free;

有一个表t1插入一行数据:第一个字段数据:num,第二个字段数据:varchar(60),第三个字段数据:varchar(40),......
插入数据: 1 abc xkj

在数据块里面怎么存的这些数据呢?
一行,头部留出一个字节来,然后后面:第一字段列的宽度9,后面跟着存上1,再接着第二字段列的宽度3,后面存上abc,第三字段列的宽度3,后面存上xkj;然后下一行,紧接着在后面加一个行头,列宽,值,列宽,值......

存储的时候,行与行之间是没有空隙的,是紧密连在一起的

访问块的时候,怎么访问的呢?
在块的头部,有一个行目录;假设这个块有10行,行目录里面记录着这10行,每一行的起始位置;找的时候,通过行目录找到行头,再找到列的位置取出数据;现在要做update,将xkj改为xkjagr,这时候,就要更改这一列的宽度,将3改为6,这一列数据之后的所有数据就要往后挪3个字节,将列宽改为6,这时候数据行的空间不够了,就要压缩free部分的空间,所以在inster的时候,不希望被挤出这个块,就使用pctfree = 10%,让它有一个预留的空间来存数据

行地址(行迁移)

在这里,每一行有一个行地址(rowid),oracle数据库里面,默认的每一行的行地址(rowid)是不能改变的;如果数据往后挪的时候,挤出一行来了,但是行地址是不能改变的,这时候就会出现行迁移(一般都是update造成的),就是说,假设现在要update一行数据,free就只有10%的空闲空间,但是对于要更新的这一行来说,10%的空闲空间不够用,oracle就会把这一行拿出来放到另外一个块里,然后,这一行原来的位置不变,在这个位置上记录着被迁移到另外一个块这一行的地址

行地址(rowid)由三部分组成:
1、文件号
2、块号(文件里面哪个块)
3、行号(文件里面第几行)

rowid是一个物理地址,可以快速的找到对应的数据行

行链接

假设,现在一个block是8k,数据库里一个表里的一行是12k,然后oracle将一行12k的数据分别存在两个块里面,一个块里面存6k,然后第一个块里面还存着在另外一个块里面的行地址

行链接是因为行数据太大,而block的空间太小,所以要使用多个block存储

行迁移和行链接都不是很好,访问性能会降低

高水位线


图解:
一个段(t1),分配了多个区,第一、二个区都用完了,第三个区用到第三个块,然后前面的块,空间大小可能不一样,有的剩余80%,有的剩余10%,有可能还有空块(被删除了),这里面的块有的空的,有的满的;然后这个区的最后一块的地址会被记录在段头块里面(表示这个段,最后一个块的地址),这个地址叫做高水位线

高水位线的含义:
假设将t1里面所有的数据全删了,然后提交,里面所有的块都是空的,但是高水位线还在那个位置;对t1插入数据的时候,高水位线往上涨,但是删除数据的时候,高水位线不变,还在原来的位置;现在t1是空的,对t1做select:select * from t1;全表扫描t1,全表扫描就是对高水位线以下所有的块扫描一遍(高水位线对全表扫描的行为影响比较大),现在t1是空的,但还是要扫描所有的块,因为高水位线还在那个位置,所以有时候我们就需要对t1做一个segment shrink(段收缩),就是将高水位线以下那些有空闲空间的块收缩,把数据收缩到一起(假设收缩到了三个块里),让它们之间没有空闲的块,然后将高水位线降下来,然后再select * from t1;的时候,就只需要访问这三个块了;
但是对一个段DML很频繁的情况下,段收缩的效果不是很好;还有一个命令:move命令,也是段收缩,这个效果很好,但是风险最大;还有就是truncate命令,就是将整个表清空了,也就是将表的段头块进行了修改,修改了高水位线,但是其实数据没有被删除,数据还在,只是高水位线指在了第一个块的位置

标签:pctfree,数据文件,及段,t1,空闲,extent,空间,区块,block
From: https://www.cnblogs.com/xgq20210831/p/18562140

相关文章

  • 《C++ 构建区块链:创世区块的初始化之道》
    在区块链这个神秘而充满魅力的技术领域中,用C++构建区块链是一项极具挑战性和创新性的工作。而其中,初始化创世区块是整个区块链大厦的基石,它承载着区块链的起源和根本属性,就像生命起源中的第一个细胞一样重要。今天,我们就来深入探讨一下在C++构建区块链时,如何进行创世区......
  • 《C++ 实现区块链:区块时间戳的存储与验证机制解析》
    在区块链这个复杂而精妙的技术架构中,时间戳是一个至关重要的元素,尤其当我们使用C++来实现区块链时,对区块时间戳的存储和验证机制设计更是不容忽视。这一机制如同区块链的时间脉搏,为整个系统的有序运行和数据可信性提供了坚实的保障。时间戳在区块链中的核心意义时间戳在......
  • 区块链
    区块链区块链概述为什么产生区块链为了解决交易信任问题区块链是什么区块链是基于密码学和共识机制组成的分布式账本核心特点去中心化:没有单一控制的节点,所有节点共同维护账本不可纂改性:一旦数据记录在区块中,几乎不可能被纂改透明性:所有交易对参与者可见(公有链)......
  • 刘艳兵-DBA034-以下关于PCTUSED和PCTFREE的说法中,哪些是正确的?
    以下关于PCTUSED和PCTFREE的说法中,哪些是正确的?A   PCTFREE设为20,表示限制数据块中只有80%的空间可用于存储新插入的行。B   PCTFREE设为20,表示限制数据块中只有20%的空间可用于存储新插入的行。C   PCTUSED设为40,表示当数据块中的已用空间低于40%时,该数据块允许......
  • 区块链交易并发: DAG 执行引擎
    早期的区块链系统,其执行引擎是一个串行执行模型,这种模型虽能保证执行的正确性,但却是区块链性能的一个核心瓶颈之一。天玄链中,通过识别交易中的状态依赖,构建交易依赖图来对执行引擎进行并行化,从而提升交易执行速度,解决该瓶颈。通用DAG分析器一个无环的有向图称做有向无环图(D......
  • HTML区块方面的细节以及表单的使用
    一.HTML中区块元素和内联元素的区别1.HTML区块元素大多数HTML元素被定义为块级元素或内联元素。块级元素在浏览器显示时,通常会以新行来开始(和结束)。(即独占一行)实例:<h1>,<p>,<ul>,<table>2.HTML内联元素内联元素在显示时通常不会以新行开始。实例:<b>,<td>,......
  • 区块反转c++
    代码#include<iostream>#include<vector>usingnamespacestd;structnode{  intdata,next;}A[100001];vector<int>L,ans,E[100001];ints,n,a,t,k,mark,cnt,c;intmain(){  cin>>s>>n>>k;  for(......
  • Hyperledger fabrics实战项目(区块链溯源)
    Hyperledgerfabrics是什么Hyperledgerfabric是一个全新解决问题的方式,是基于区块链的企业级分布式账本,通过智能合约来解决多个组织间的信任问题.Hyperledgerfabrics特点模块化:组件可定制,可插拔设计,隔离功能可扩展:支持多个共识机制,高性能处理,分区和多通道超安......
  • 【PAT_Python解】1110 区块反转
    原题链接:PTA|程序设计类实验辅助教学平台Tips:以下Python代码仅个人理解,非最优算法,仅供参考!多学习其他大佬的AC代码!importsys#读取输入head,n,k=map(int,sys.stdin.readline().split())#初始化数据,装入字典,最终取值data={}next={}for_inrange(n):......
  • 在区块链技术中,什么是工作量证明(PoW)?
    工作量证明(Proof-of-Work,PoW)是区块链网络中的一种共识机制。它是一种用于验证节点是否为区块链的维护和扩展付出了足够计算资源(即工作量)的方法。通过让节点完成一个具有一定难度的计算任务,来竞争在区块链上添加新区块的权力。简单理解,就像是一场竞赛,参赛者(节点)需要完成一......