ORACLE的块、区、段、表空间简述

ORACLE在逻辑存储上分4个粒度:块、段、区、表空间。

2.1 块: 是粒度最小的存储单位,默认的块大小是8K,( 为什么Oracle要用数据块作为最小单位?因为,无论是Windows环境,还是Unix/Linux环境,他们的操作系统存储结构和方式、甚至字符排列的方式都是不同的。所以,Oracle利用数据块将这些差异加以屏蔽,全部数据操作采用对Oracle块的操作,相当于是对底层环境的一层封装。)ORACLE每一次 I/O 操作也是按块来操作的,也就是说当ORACLE从数据文件读数据时,是读取多少个块,而不是多少行。每一个Block里可以包含多个row。【延伸:mysql是页、区、段,pg最小单位也是块,本质一样。】


2.2 区:一系列相邻的块而组成,这也是ORACLE 空间分配的基本单位,举个例子来说,当我们创建一个表A时,首先ORACLE会分配一区的空间给这个表,随着不断的INSERT数据到A表,原来的这个区容不下插入的数据时, ORACLE 是以区为单位进行扩展的,也就是说再分配多少个区给A表,而不是多少个块。在进行存储数据信息的时候,Oracle将分配数据块进行存储,但是不能保证所有分配的数据块都是连续的结构。所以, 出现分区extent的概念,表示一系列连续的数据块集合。

  --查看区信息
  SET LIN 200 PAGES 999
  COL OWNER FOR A20
  COL SEGMENT_NAME FOR A20
  COL SEGMENT_TYPE FOR A10
  COL TABLESPACE_NAME FOR A10
  select  OWNER,SEGMENT_NAME,SEGMENT_TYPE,TABLESPACE_NAME,EXTENT_ID,FILE_ID,BLOCK_ID,BLOCKS  from dba_extents 
  where TABLESPACE_NAME='USERS' AND OWNER='SCOTT'  order by 7;
  



从视图中,我们可以清晰看出分区的几个特点:

首先分区是带有段特定性的。数据段segment是分区的上层组织单位,一个数据库对象对应一个segment,数据库对象是归属在不同的schema(owner)上的。所以,通过不同的数据段名称、不同的owner,乃至不同的tablespace表空间信息,就可以定位到数据区extent的信息描述。

另一部分信息是关于该区extent的分配信息,如所在文件编号,起始数据块block编号和数据块数量等内容。图中可以看到由于EXTENT_ID一致时,只需要定位开始的block就知道这些块是否连续,一般block_id间隔8。
这里再做一个测试,判断批量插入是否是连续的块:

  
-- 创建测试表a:
  
create table  scott.a (id number) tablespace users;
  
insert into scott.a  SELECT OBJECT_ID FROM DBA _OBJECTS;
  
commit;
  



从EXTENT_ID不一致分布,可以看到插入的时候并不是连续块插入的,而且采用随机I/O的插入到不同的区中,但是又有一定的规律。
那么为什么要写入不同的区中呢?

猜想:现在存储一般都使用磁盘阵列,提高存储性能的原理是把连续的数据分散到多个磁盘上存取,这样,系统有数据请求就可以被多个磁盘并行的执行,每个磁盘执行属于它自己的那部分数据请求。这种数据上的并行操作可以充分利用总线的 带宽,显著提高磁盘整体存取性能。
所以应该是为了能够充分利用每块磁盘的性能,所以才要写到不的分区中,也就是说分区概念中的连续的块集合,应该是一种块逻辑连续的概念,在物理上也不是连续的。

这里做一个10046的读取测试,看看读取时的信息:
  --10046测试
  ALTER SESSION  SET EVENTS '10046 TRACE NAME CONTEXT FOREVER,LEVEL 12';
  select count(*)  from scott.a;
  select value  from v$diag_info where name='Default Trace File';
  



可以看到先对1690这个块( 从dba_segments可以查到这个是个块头)做了一个单块读,获取其余块的信息,然后进行了一系列的多块读,可以发现一次 读取的最大块数为一个extent的大小,这里为8,所以分区在读取数据的意义应该是有一个限流的作用。
这里再扩展一个参数: db_file_multiblock_read_count,可以加大每次I/O获取的最大块数,但是还是会受extent大小的影响。

  
-- 创建测试表c:
  
create table scott.c (id number) tablespace users;
  
insert into scott.c SELECT  OBJECT_ID FROM DBA_OBJECTS;
  
insert into scott.c SELECT  OBJECT_ID FROM DBA_OBJECTS;
  
commit;
  
-- 设参数为20
  
alter system set db_file_multiblock_read_count=20;

--10046测试
  ALTER SESSION  SET EVENTS '10046 TRACE NAME CONTEXT FOREVER,LEVEL 12';
  select count(*)  from scott.c;
  
select value from v$diag_info  where name='Default Trace File';
  

-- 看到 C 表信息,看到 EXTENT_ID= 16 128 个块




-- 参数 db_file_multiblock_read_count 设为20


--10046 报告




从上图可以看到多块读的数量收到了参数 db_file_multiblock_read_count的限制。所以一些olap系统上可以提高这个参数,另外增大块大小来提高单次I/O的效率。

-- 第三个实验是把db_file_multiblock_read_count设为256,全表扫描C表,一次最大只能读取128这个块,因为这个参数不能超过一个extent的大小。




逻辑概念与物理存储关系图

2.2 段:是由一系列的区所组成,一般来说,当创建一个对象时(例如:表,索引),就会分配一个段给这个对象。所以从某种意义上来说,段就是某种特定的数据。如 CREATE TABLE A,这个段就是数据段,而 CREATE INDEX ON A(ID), ORACLE同样会分配一个段给这个索引,这是一个索引段。查询段的信息可以通过数据字典: SELECT * FROM DBA_SEGMENTS来获得。





2.4 表空间: Oracle的表空间属于Oracle中的存储结构,是一种用于存储数据库对象(如:数据文件)的逻辑空间,是Oracle中信息存储的最大逻辑单元,其下还包含有段、区、数据块等逻辑数据类型。表空间是在数据库中开辟的一个空间,用于存放数据库的对象,一个数据库可以由多个表空间组成。可以通过表空间来实现对Oracle的调优。


表空间实际上是由若干个数据文件来构成的,数据文件的位置和大小可以由我们自己来决定。数据被存放在表空间中的数据文件中。








管理表空间的方式:



字典管理表空间(Dictionary-ManagedTablespace简称DMT)

8i以后出现的一种新的表空间的管理模式,通过本地位图来管理表空间的空间使用。



本地管理表空间(LocallyManaged Tablespace简称LMT)

8i以前包括以后都还可以使用的一种表空间管理模式,通过数据字典管理表。



一、 本地管理表空间的由来:


在Oracle8I的版本中,Oracle推出了一种全新的表空间管理方式:本地化管理的表空间。所谓本地化管理,就是指Oracle不再利用数据字典表来记录Oracle表空间里面的区的使用状况,而是在每个表空间的数据文件的头部加入了一个位图区,在其中记录每个区的使用状况。每当一个区被使用,或者被释放以供重新使用时,Oracle都会更新数据文件头部的这个记录,反映这个变化。

  --查看表空间管理方式
  select tablespace_name,extent_management, allocation_type from  dba_tablespaces;

  

Oracle之所以推出了这种新的表空间管理方法,让我们来看一下这种表空间组织方法的优点:

       1. 本地化管理的表空间避免了递归的空间管理操作。而这种情况在数据字典管理的表空间是经常出现的,当表空间里的区的使用状况发生改变时,数据字典的表的信息发生改变,从而同时也使用了在系统表空间里的回滚段。

2.本地化管理的表空间避免了在数据字典相应表里面写入空闲空间、已使用空间的信息,从而减少了数据字典表的竞争,提高了空间管理的并发性。


3.从由数据字典来管理空闲块改为由数据文件的头部记录来管理空闲块,这样避免产生回滚信息,不再使用系统表空间里的回滚段。因为由数据字典来管理的话,它会把相关信息记在数据字典的表里,从而产生回滚信息。由于这种表空间的以上特性,所以它支持在一个表空间里边进行更多的并发操作,并减少了对数据字典的依赖。


二、本地管理表空间管理机制


8i之前所有的表空间都是采用字典管理模式,ORACLE需要有一个机制来管理表空间中各数据文件的这些分配的或未分配的空间,为了跟踪这些可以使用的空间(包括未分配使用的和可以重复使用的),对于每一个空间,我们必须知道:


      1、这个可用空间位于什么数据文件;
      2、这个空间的尺寸是多大;
      3、如果它在用了,是哪一个段占用的这个空间;


为了确保能保存以上的信息,ORACLE用了两个数据字典表:UET$(已使用的区间)或FET$(空闲空间):



查询该表可以看到,每个使用空间或空闲空间(不一定是一个extent,可以是多个extent)都在该表中对应了一行。它的工作方式是当一个段被删除的时候,ORACLE就移动UET$中相应的行到FET$,这个过程的发生是连续的,而且可能发生等待。当并发性很高的时候,数据字典的争用就来了。另外有一个问题就是,当表的空间很不连续或表空间有大量的碎片引起这两个表的增大,那么也就会引起数据库性能上的下降。


本地管理表空间正是为了解决这一问题来的,在表空间的空间管理上,ORACLE将存储信息保存在表空间的头部的位图中,而不是保存在数据字典中。通过这样的方式,在分配回收空间的时候,表空间就可以独立的完成操作也不用与其它对象关系。
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
sql语句来练习题。1. 写出创建图书表的SQL语句。 Create table book( Book_id char (10) primary key, (主码primary key) Name varchar(30) not null, (非空not null) Author varchar(20) Publish varchar(30) Price decimal(6,2) (,前表示有几位有效数字 ,后表示小数部分有几位) ) 2. 将编号为“NEU1105101”的图书的定价改为50元。 Update book (修改数据update语句) Set price=50 Where book_id=‘NEU1105101’ 3. 查询所有男性读者的姓名和出生日期。 Select name.birthdate From reader Where sex=‘男’ 4. 查询图书表中出现过哪些出版社,每个出版社名称只显示一次,并且按照出版社名称升序排列显示。 Select publish From book Order by publish ASC (按照出版社升序排列显示) 5. 查询借阅过定价介于20元到40元(包括两个边界值)图书的读者的姓名。 Select Name (建立多表连接查询) From borrow join book on borrow.book_id=book.book_id Join reader on borrow.reader_id=reader.readerid Where price >=20 and price <=40 6. 查询每个读者借阅过图书的数量,只显示借阅过图书的读者的读者编号以及借书数量。 Select count(book_id),reader_id (建立多表连接查询) From borrow join book on borrow.book_id=book.book_id Join reader on borrow.reader_id=reader.readerid Group by reder_id 7. 如果有一个名为user001的用户,请写出给他分配对图书表进行数据修改的权限的SQL语句。 Grant update on book to user001 (授权grant语句) 8. 创建一个名为view001的视图,其中包含每个出版社的名称、该出版社出版图书的数量、该出版社出版图书的最高定价、以及该出版社出版图书的最低定价。 Create view view001 (创建视图格式,聚集函数) AS Select publish,count(book_id),MAX(price),MIN(price) From student 9. 显示借阅过书名包含“数据库”字样的女性读者的编号和姓名。 Select Name,reader_id (建立多表连接查询) From borrow join book on borrow.book_id=book.book_id Join reader on borrow.reader_id=reader.readerid Where name like ‘%数据库%’ 10. 显示出版图书数量超过100本的出版社的名称及其出版图书的数量。 Select count(book_id),publish (查询图书数量,出版社名称) From book Group by publish (根据出版社的名称来分组) Having count(book_id)>100 (条件约束) 这里用having 不用where 原因是它不能和聚集函数一起使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值