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命令,就是将整个表清空了,也就是将表的段头块进行了修改,修改了高水位线,但是其实数据没有被删除,数据还在,只是高水位线指在了第一个块的位置

23、表空间及段区块_1(段区块管理、pctfree、数据块结构、行迁移、高水位)的更多相关文章

  1. ORA-01652:无法通过128(在表空间temp中)扩展temp段 解决方法

    ORA-01652:无法通过128(在表空间temp中)扩展temp段 解决方法 (2016-10-21 16:49:53)   今天在做一个查询的时候,报了一个"ORA-01652无法通过 ...

  2. ora-01652无法通过128(在表空间temp中)扩展temp段

    今天提交请求后,提示ORA-01652: 无法通过 128 (在表空间 TEMP 中) 扩展 temp 段.最后通过ALTER DATABASE TEMPFILE '/*/*/db/apps_st/d ...

  3. 解决ora-01652无法通过128(在temp表空间中)扩展temp段的过程

    解决ora-01652无法通过128(在temp表空间中)扩展temp段的过程 昨天开发人员跟我说,执行一个sql语句后,大约花了10分钟,好不容易有一个结果,但是报了一个ora-01652错误,查阅 ...

  4. 解决ora-01652无法通过128(在表空间temp中)扩展temp段

    问题描述: 今天建索引的时候报:ora-01652无法通过128(在表空间temp中)扩展temp段 1.查看表空间是自动增长,且建表空间时是没有设表空间最大值的. 2.查看了一下表空间剩余多少竟然只 ...

  5. ORA-01652:无法通过128(在表空间TEMP中)扩展temp段

    在Oracle数据库中进行order by or group by.索引的创建和重创建.distinct操作.union & intersect & minus sort-merge ...

  6. ORA-01652: 无法通过 128 (在表空间 TEMP 中) 扩展 temp 段(EXP-00056: 遇到 ORACLE 错误 1652 ORA-01652: unable to extend temp segment by 128 in tablespace TEMP)

    数据库报 ORA-01652: 无法通过 128 (在表空间 TEMP 中) 扩展 temp 段 两种解决方式: 第一种) sql>select * from v$tempfile; 发现tem ...

  7. ORA-01652: 无法通过 128 (在表空间 HIS_TABLESPACE_TEMP 中) 扩展 temp 段

    前言:采用jmeter进行压力测试,大概向oracle 添加了140W条数据. 结果系统涉及到该表的业务都异常卡.访问阿里巴巴的那个druid monitor,因为系统中集成了,查看sql监控中的sq ...

  8. ora-01652无法通过128(在temp表空间中)扩展temp段

    有两种错误:1.数据表空间不足 2.临时表空间不足 有两种原因:一是临时表空间空间太小,二是不能自动扩展. 分析过程:    既然是temp表空间有问题,那当然就要从temp表空间说起啦.首先要说明的 ...

  9. 无法通过 128 (在表空间 TEMP 中) 扩展 temp 段

    1.查看表空间中数据文件存储的路径以及是否可以自动扩展 SELECT TABLESPACE_NAME, BYTES/1024/1024 FILE_SIZE_MB, FILE_NAME FROM DBA ...

  10. orale数据库.实例.表空间.用户.表

    近期因为工作原因接触到Oracle数据库.了解到Oracle和mysql的结构上还是有很大的区别的. Oracle数据库---实例---表空间---用户---表 我们将从这5个方面来了解Oracle ...

随机推荐

  1. VMware 安装 OpenWrt

    准备 OpenWrt VMDK 固件映像 你可以直接下载 VMDK 版本的 OpenWrt 固件映像,或者自己构建一个,或者从 IMG 映像文件转换.一般来说 IMG 映像文件较为容易获取,因此下面介 ...

  2. 【Azure Policy】添加策略用于审计Azure 网络安全组(NSG)规则 -- 只能特定的IP地址允许3389/22端口访问

    问题描述 对Azure上的虚拟机资源,需要进行安全管理.只有指定的IP地址才能够通过RDP/SSH远程到虚拟机上, 有如下几点考虑: 1) 使用Azure Policy服务,扫描订阅中全部的网络安全组 ...

  3. sicp每日一题[1.44]

    Exercise 1.44 The idea of smoothing a function is an important concept in signal processing. If f is ...

  4. 事务TRANSACTION 1

    MySQL事务是指一组SQL语句作为一个工作单元,同生共死.类似JS中的Array.prototype.every方法 事务的特点 原子性(Atomicity):即事务中的SQL像原子一样牢不可破,无 ...

  5. OData – Query to Expression

    前言 EF Core 可以把 expression 转换成 string, 但没办法转回来. 想把 string 转成 expression, 目前最合适的工具是 OData. 虽然 Dynamic ...

  6. Spring —— bean配置

    基础配置      别名配置    作用范围配置      适合交给容器进行管理的bean   (复用性的对象,无需重复创建的对象) 表现层对象 业务层对象 数据层对象 工具对象   不适合交给容器管 ...

  7. [34](CSP 集训)CSP-S 联训模拟 1

    A 几何 重复若干次 -> 不能重叠,因此考虑直接暴力 DP 设 \(f_{i,j,k}\) 表示主串匹配到第 \(i\) 位(将前 \(i\) 位分别归为两类),其中 \(x\) 在重复了若干 ...

  8. 阿里邮箱网页正常登陆,outlook报错

    事件起因: 某客户使用阿里邮箱办公,然又使用outlook绑定阿里邮箱:在网页端可以登录阿里邮箱,但是在outlook的登录的时候,服务器.端口均设置无误,但是就是登录不上去,死活都等登录不上去,总是 ...

  9. 下载 Youtube 上的视频的方法

    事件起因: 某项目组同事需要下载 Youtube 上的视频作为参考视频 解决办法: https://www.converto.io/ -= 实测有效 =-  我个人一直在用该网站可以下载,非常好用,下 ...

  10. IT运维工单高效协同,助力打造一站式运维方案

    随着经济全球化的发展趋势,信息系统在企业运营中占据着愈发重要的位置.业务系统越来越多,用户对信息系统的依赖性越来越强,关键业务系统的中断都将导致企业业务.服务的中断,极大的影响了企业业务稳定运行和持续 ...