Oracle学习

来源:互联网 发布:经济杂志 知乎 编辑:程序博客网 时间:2024/05/06 01:06

Block 块

Oracle块是建筑数据库的基石。是数据库的最小i/o单位。Oracle读取数据文件时是以块的形式读取的。data block的大小是操作系统的data block的整数倍,ORACLE默认是8K,还有4K16K32k几种。

 一个Oracle   block由三个部分组成,分别是数据块头、自由空间、实际数据三部份组成。  

数据块头:主要包含有数据块地址的一些基本信息和段的类型,以及表和包含有数据的实际行的地址。  

自由空间:是指可以为以后的更新和插入操作分配的空间,大小由PCTFREEPCTUSED两个参数影响。  

实际数据:是指在行内存储的实际数据。  当创建或者更改任何表和索引的时候,Oracle在空间控制方面使用两个存储参数:  PCTFREE:为将来更新已经存在的数据预留空间的百分比。  PCTUSED:用于为插入一新行数据的最小空间的百分比。这个值决定了块的可用状态。可用的块时可以执行插入的块,不可用状态的块只能执行删除和修改,可用状态的块被放在freelist中。

 当表中一行的数据不能在一个数据block中放入的时候,这个时候就会发生两种情况,一种是行链接,另外一种就是行迁移了

行链接产生在第一次插入数据的时候如果一个block不能存放一行记录的情况下。这种情况下,Oracle将使用链接一个或者多个在这个段中保留的 block存储这一行记录,行链接比较容易发生在比较大的行上,例如行上有LONGLONG   RAWLOB等数据类型的字段,这种时候行链接是不可避免的会产生的。  当一行记录初始插入的时候事可以存储在一个block中的,由于更新操作导致行长增加了,而block的自由空间已经完全满了,这个时候就产生了行迁移。在这种情况下,Oracle将会迁移整行数据到一个新的block中(假设一个block中可以存储下整行数据),Oracle会保留被迁移行的原始指针指向新的存放行数据的block,这就意味着被迁移行的ROW   ID是不会改变的。  当发生了行迁移或者行链接,对这行数据操作的性能就会降低,因为Oracle必须要扫描更多的block来获得这行的信息。 行链接主要是由于数据库的db_block_size不够大,对于一些大的字段没法在一个block中存储下,从而产生了行链接。对于行链接我们除了增大db_block_size之外没有别的任何办法去避免,但是因为数据库建立后db_block_size是不可改变的(在9i之前),对于Oracle9i的数据库我们可以对不同的表空间指定不同的db_block_size,因此行链接的产生几乎是不可避免的,也没有太多可以调整的地方。 
       
行迁移则主要是由于更新表的时候,由于表的pctfree参数设置太小,导致block中没有足够的空间去容纳更新后的记录,从而产生了行迁移。对于行迁移来说就非常有调整的必要了,因为这个是可以调整和控制清除的。

 

 

 

 

 

Extent 区

Extent 区是一次分配的,连续的,oracle块。

建立表时分配新的区(extent)10g,11g中不会立刻分配区,只有插入了第一条数据后才会分配区。注意版本的区别。表建立的时候会分配新的空间,这个空间叫做初始区InitialExtent,即使是一个空表也有初始区EXTENT10g之前的版本,11g后只有插入第一条数据后才分配),初始区EXTENT和其它以后的区EXTENT都不同,因为初始区EXTENT中含有表头块,这个数据块中没有我们的数据。首先数据库要找到在哪个表空间中分配空间,如果我们在建立表的时候没有指明,那么就从默认表空间中分配

如果数据库已经为一张很大的表逐渐分配了168数据块的区,共分配了1M的空间,我们还要求分配新的空间,数据库认为这个表很大,所以就一次分了128个数据块。如果我们再增加表的大小,数据库会分配多个1m,以后就8m为大小分配,再以后就64m大小分配。总之是一个原则,我们现有的数据越大,未来的范围就越大

 

 

Segment段

数据段是与数据库对象相对应,一般一个数据库对象对应一个数据段。通过多个extent是对应一个数据段,每个数据段实际上就是数据库一个对象的代表。通过descdba_segments查看段的类型

Type of segment:  "TABLE","CLUSTER", "INDEX", "ROLLBACK",

"DEFERRED ROLLBACK","TEMPORARY","SPACE HEADER", "TYPE2 UNDO"  or"CACHE"

 

分区实际上就是存在分开存储的可能。一般一个对象是不会跨物理存储进行存放的,分区表是对应的多个segment。所以,分区表分开存储空间是可能的。

 

 

Tablespace表空间

TableSpace是存储结构中的最高层结构。建立一个表空间的时候,是需要指定存储的文件datafile。一个表空间可以指定多个数据文件,多个文件可以在不同的物理存储上。也就是说,表空间是可以跨物理存储的。但是有一点就是,表空间下一级对象数据段的存储,是不能指定存储在那个文件里的。所以,要想让数据对象访问IO负载均衡,需要指定不同的数据对象在不同的表空间里。这也就是为什么将数据表和索引建立在不同的表空间的原因。

 

HWM高水位线

所有的oracle段都有一个在segment段内容纳数据的上限,我们把这个上限称为"high watermark"HWM。这个HWM是一个标记,用来说明已经有多少没有使用的数据块分配给这个segmentHWM通常增长的幅度为一次5个数据块,原则上HWM只会增大,不会缩小,即使将表中的数据全部删除,HWM还是为原值,由于这个特点,使HWM很象一个水库的历史最高水位,这也就是HWM的原始含义,当然不能说一个水库没水了,就说该水库的历史最高水位为0。但是如果我们在表上使用了truncate命令,则该表的HWM会被重新置为0

select blocks,empty_blocks from dba_tables where table_name='xxx' and owner='xx';

blocks就是已经分配的空间即HWM,实际分配的空间,不是实际大小。Empty_blocks就是HWM上的数据块

降低HWM

analyze table abc compute statistics;

alter table SCORE enable row movement; --重组数据

alter table SCORE shrink space;         --降低高水位

 

Shrink Table表空间收缩

10g开始,oracle开始提供Shrink的命令,假如我们的表空间中支持自动段空间管理 (ASSM),就可以使用这个特性缩小段,即降低HWM。这里需要强调一点,10g的这个新特性,仅对ASSM表空间有效,否则会报 ORA-10635:Invalid segment or tablespace type 如果经常在表上执行DML操作,会造成数据库块中数据分布稀疏,浪费大量空间。同时也会影响全表扫描的性能,因为全表扫描需要访问更多的数据块。从oracle10g开始,表可以通过shrink来重组数据使数据分布更紧密,同时降低HWM释放空闲数据块。

 segmentshrink分为两个阶段:

1、数据重组(compact):通过一系列insertdelete操作,将数据尽量排列在段的前面。在这个过程中需要在表上加RX锁,即只在需要移动的行上加锁。由于涉及到rowid的改变,需要enable rowmovement.同时要disable基于rowidtrigger.这一过程对业务影响比较小。

2HWM调整:第二阶段是调整HWM位置,释放空闲数据块。此过程需要在表上加X锁,会造成表上的所有DML语句阻塞。在业务特别繁忙的系统上可能造成比较大的影响

shrink space语句两个阶段都执行。

shrink spacecompact只执行第一个阶段。

如果系统业务比较繁忙,可以先执行shrink spacecompact重组数据,然后在业务不忙的时候再执行shrink space降低HWM释放空闲数据块。

shrink必须开启行迁移功能。

alter tabletable_name enable row movement ;

注意:alter table XXXenable row movement语句会造成引用表XXX的对象(如存储过程、包、视图等)变为无效。执行完成后,最好执行一下utlrp.sql来编译无效的对象。

语法:

alter table<table_name> shrink space [ <null> | compact | cascade ];

alter table<table_name> shrink space compcat;

收缩表,相当于把块中数据打结实了,但会保持 high watermark;

alter table<tablespace_name> shrink space;

收缩表,降低 high watermark;

Alter  table <tablespace_name> shrink spacecascade –此语句会同时收缩索引区;

收缩表,降低 high water mark,并且相关索引也要收缩一下下。

alter indexidxname shrink space;

回缩索引

当执行了shrink操作后,有意思的现象出现了。我们来看看oracle是如何移动行数据的,这里的情况和move已经不太一样了。我们知道,在move操作的时候,所有行的rowid都发生了变化,table所位于的block的区域也发生了变化,但是所有行物理存储的顺序都没有发生变化,所以我们得到的结论是,oracleblock为单位,进行了block间的数据copy。那么shrink后,我们发现,部分行数据的rowid发生了变化,同时,部分行数据的物理存储的顺序也发生了变化,而table所位于的block的区域却没有变化,这就说明,shrink只移动了table其中一部分的行数据,来完成释放空间,而且,这个过程是在table当前所使用的block中完成的。

那么Oracle具体移动行数据的过程是怎样的呢?我们根据这样的实验结果,可以来猜测一下:

Oracle是以行为单位来移动数据的。Oracle从当前table存储的最后一行数据开始移动,从当前table最先使用的block开始搜索空间,所以,shrink之前,rownum10的那行数据(10,es),被移动到block AAAAEc上,写到(1,aa)这行数据的后面,所以(10,es)的rownumrowid同时发生改变。然后是(9,es)这行数据,重复上述过程。这是oracle从后向前移动行数据的大致遵循的规则,那么具体移动行数据的的算法是比较复杂的,包括向ASSMtableinsert数据使用block的顺序的算法也是比较复杂的,在shrink table的同时shrink这个table上的index

alter tablemy_objects shrink space cascade;

同样地,这个操作只有当table上的index也是ASSM时,才能使用。

Move Shrink产生日志的对比

我们对比了同样数据量和分布状况的两张table,在moveshrink下生成的redo sizetable上没有index的情况下): 

Shrink的几点问题:

1.     shrinkindex是否需要rebuild

因为shrink的操作也会改变行数据的rowid,那么,如果table上有index时, shrink在移动行数据时,也一起维护了index上相应行的数据rowid的信息。我们认为,这是对于move操作后需要rebuild index的改进。但是如果一个table上的index数量较多,我们知道,维护index的成本是比较高的,shrink过程中用来维护index的成本也会比较高。

2. shrink时对tablelock

在对table进行shrink时,会对table进行怎样的锁定呢?当我们对table MY_OBJECTS进行shrink操作时,查询v$locked_objects视图可以发现,table MY_OBJECTS上加了row-X (SX)lock

shrink时,我们对table是可以进行DML操作的。

3 shrink对空间的要求

我们在前面讨论了shrink的数据的移动机制,既然oracle是从后向前移动行数据,那么,shrink的操作就不会像move一样,shrink不需要使用额外的空闲空间。

 

直接路径加载插入

使用append提示进行insert叫做直接路径加载插入。

1、使用这种提示因为系统不去查找freelist链表中的空闲块,直接在高水标记位以上插入数据,因此速度比较快。但若是对于经常delete的表,浪费磁盘空间太大!

2、它不记录日志,因此一旦插入的数据在没有保存回磁盘的时候发生掉电之类的状况插入的数据不能重做。

3/*+append*/后,需要马上提交,否则会影响下一次修改失败

Oracle Database10g Enterprise Edition Release 10.2.0.1.0中,如果插入操作的语法是

insert /*+append*/ intoXXX values(XXX);

那么系统加的是row exclusive锁,也就是正常insert所加的行级锁,但是如果插入操作的语法是

insert /*+append*/ intoXXX select XXX from XXX;

那么系统加的是exclusive锁,相当于表级锁,加表级锁意味着在本会话没有commit的时候其他任何会话都不能再进行insert,update,delete操作

4.配合修改表不记录log速度更快

Alert table score nologging

 

压缩表

Orcle9i2版中,表压缩特性通过删除在数据库表中发现的重复数据值来节省空间。压缩是在数据库的数据块级别上进行的。当确定一个表要被压缩后,数据库便在每一个数据库数据块中保留空间,

以便储存在该数据块中的多个位置上出现的数据的单一拷贝。这一被保留的空间被称作符号表(symbol table)。被标识为要进行压缩的数据只存储在该符号表中,而不是在数据库行本身内。当在一个

数据库行中出现被标识为要压缩的数据时,该行在该符号表中存储一个指向相关数据的指针,而不是数据本身。节约空间是通过删除表中数据值的冗余拷贝而实现的。

 

字符集

Oracle在插入和查询主要涉及到4个字符集,操作系统字符集(os字符集),oracle客户端注册表字符集,环境变量NLS_LANG,数据库字符集。Oracle客户端和环境变量NLS_LANG都是用来标识客户端字符集,当两个字符集不一样时,以NLS_LANFG为主,如果没有环境变量NLS_LANG则用客户端注册表信息标识客户端字符集。

当客户端向oracle发送数据时,发送的是os字符集编码的数据,oracle检测数据库字符集是否和客户端字符集一致,如果一致则直接存储,如果不一致则转码为据库字符集存储,查询的时候,oracle会检测数据库字符集是否和客户端字符集一致,如果一致则直接输出,如果不一致则转码为客户端字符集输出,然后将输出的字符在os字符集上显示出来。

参考http://blog.itpub.net/545828/viewspace-1026559/

0 0