oracle-数据库表-术语

1. 表类型

Oracle中主要有9种表类型:

堆组织表(heap organized table)

这些就是“普通”的标准数据库表。数据以堆的方式管理。增加数据时,会使用段中找到的第一个能放下此数据的自由空间。从表中删除数据时,则允许以后的INSERT和UPDATE重用这部分空间。这就是这种表类型中的“堆”这个名词的由来。堆(heap)是一组空间,以一种有些随机的方式使用。

索引组织表(index organized table)

这些表按索引结构存储。这就强制要求行本身有某种物理顺序。在堆中,只要放得下,数据可以放在任何位置;而索引组织表(IOT)有所不同,在IOT中,数据要根据主键有序地存储

索引聚簇表(index clustered table)

聚簇(cluster)是指一个或多个表组成的组,这些表物理地存储在相同的数据库块上,有相同聚簇键值的所有行会相邻地物理存储。这种结构可以实现两个目标。首先,多个表可以物理地存储在一起。一般而言,你可能认为一个表的数据就在一个数据库块上,但是对于聚簇表,可能把多个表的数据存储在同一个块上。其次,包含相同聚簇键值(如DEPTNO=10)的所有数据会物理地存储在一起。这些数据按聚簇键值“聚簇”在一起。聚簇键使用B*树索引 建立。

散列聚簇表(hash clustered table)

这些表类似于聚簇表,但是不使用B*树索引聚簇键来定位数据,散列聚簇将键散列到聚簇上,从而找到数据应该在哪个数据库块上。在散列聚簇中,数据就是索引。如果需要频繁地通过键的相等性比较来读取数据,散列聚簇表就很适用。

有序散列聚簇表(sorted hash clustered table)

它结合了散列聚簇表的某些方面,同时兼有IOT的一些方面。其概念如下:你的行按某个键值(如CUSTOMER_ID)散列,而与该键相 关的一系列记录以某种有序顺序到达(因此这些记录是基于时间戳的记录),并按这种有序顺序处理。例如,客户在你的订单输入系统中下订单,这些订单会按先进 先出(first in, first out, FIFO)的方式获取和处理。在这样一个系统中,有序散列聚簇就是适用的数据结构。

嵌套表(nested table)

嵌套表是Oracle对象关系扩展的一部分。它们实际上就是系统生成和维护的父/子关系中的子表。嵌套表的工作类似于SCOTT模式中的 EMP和DEPT。可以认为EMP是DEPT表的子表,因为EMP表有一个指向DEPT的外键DEPTNO。嵌套表与子表的主要区别是:嵌套表不像子表 (如EMP)那样是“独立”表。

临时表(temporary table)

这些表存储的是事务期间或会话期间的“草稿”数据。临时表要根据需要从当前用户的临时表空间分配临时区段。每个会话只能看到这个会话分配的区段;它从不会看到其他任何会话中创建的任何数据。

对象表(object table)

对象表基于某种对象类型创建。它们拥有非对象表所没有的特殊属性,如系统会为对象表的每一行生成REF对象标识符)。对象表实际上是堆组织表、索引组织表和临时表的特例,还可以包含嵌套表作为其结构的一部分。

外部表(external table)

这些表并不存储在数据库本身中,而是放在数据库之外,即放在平常的操作系统文件中。利用外部表可以查询数据库之外的一个文件,就好像这个文件也是数据库中平常的表一样。外部表对于向数据库加载数据最有用(外部表是非常强大的数据加载工具)。Oracle 10g 还引入了一个外部表卸载功能,在不使用数据库链接的情况下,这为在Oracle数据库之间移动数据提供了一种简单的方法。

不论哪种类型的表,都有以下一般信息:

1. 一个表最多可以有1000列。Oracle在内部会把列数大于254的行存储在多个单独的行段(row piece)中,这些行段相互指向,而且必须重新组装为完整的行影像。

2. 表的行数几乎是无限的。例如,一般来讲,一个表空间最多有1022个文件。假设你有一些32GB的文件,也就是说,每个表空间有 32,704GB,就会有2,143,289,344个块,每个块大小为16KB。你可能在每个块上放160行(每行大约80~100字节)。这样就会有 342,926,295,040行。不过,如果对这个表分区,这个行数还能很容易地翻倍。例如,假设一个表有1024个散列分区,则能有1024× 342,926,295,040行。

3. 表中的列有多少种排列(以及这些列的函数有多少种排列),表就可以有多少个索引。随着基于函数的索引的出现,理论上讲,说能创建的索引数是无限的!

4. 即使在一个数据库中也可以有无限多个表。

2 术语

2.1段

Oracle中的段(segment)是占用磁盘上存储空间的一个对象。最常见的段类型如下:
a) 聚簇(cluster):这种段类型能存储表。有两种类型的聚簇:B*树聚簇和散列聚簇。聚簇通常用于存储多个表上的相关数据,将其“预联结”存储到同一个数据库块上;还可以用于存储一个表的相关信息。“聚簇”这个词是指这个段能把相关的信息物理的聚在一起
b) 表(table):表段保存一个数据库表的数据,这可能是最常用的段类型,通常与索引段联合使用。
c) 表分区(table partition)或子分区(subpartition):这种段类型用于分区,与表段很相似。分区表由一个或多个分区段(table partition segment)组成,组合分区表则由一个或多个表子分区段(table subpartition segment)组成。
d) 索引(index):这种段类型可以保存索引结构。
e) 索引分区(index partition):类似与表分区,这种段类型包含一个索引的某个片。分区索引由一个或多个索引分区段(index partition segment)组成。
f) Lob分 区(lob partition)、lob子分区(lob subpartition)、lob索引(lobindex)和lob段(lobsegment):lobindex和lobsegment段保存大对象 (large object或LOB)的结构。对包含LOB的表分区时,lobsegment也会分区,lob分区段(lob partition segment)正是用于此。
g) 嵌套表(nested table):这是为嵌套表指定的段类型,它是主/明细关系中一种特殊类型的“子”表。
h) 回滚段(rollback)和Type2 undo段:undo数据就存储在这里。回滚段是DBA手动创建的段。Type2 undo段由Oracle自动创建和管理。

举例来说,一个表可以是一个段。索引有可能是一个段。我们可以把一个索引划分到不同的段中。所以,索引对象本身只是一个定义,而不是一个物理段,索引可能由多个索引分区组成,而每个索引分区(index partition)是一个段。表可能是一个段,也可能不是。由于同样的原因,由于表分区,一个表可以有多个表段:或者可以在一个称为聚簇的段中创建一个表,此时这个表可能与其他表同在一个聚簇段中。

不过,最常见的情况是,表是一个段,索引也是一个段。创建一个表时,通常就是创建一个新的表段,这个段包含区段,区段则包含块。这是平常的存储层次结构。但是要指出重要的一点,只在“通常”情况下才有这种一对一的关系。例如,考虑以下这个简单的CREATE TABLE语句:

scott@ORCL>Create table t ( x int primary key, y clob, z blob );

表已创建。

这个语句创建6个段。如果在一个初始为空(什么也没有)的模式中发出下面的CREATE TABLE语句,会观察到以下结果:
ops$tkyte@ORA10G> select segment_name, segment_type
2 from user_segments;
no rows selected


ops$tkyte@ORA10G> create table t ( x int primary key, y clob, z blob );
Table created.


ops$tkyte@ORA10G> select segment_name, segment_type
2 from user_segments;
SEGMENT_NAME SEGMENT_TYPE
------------------------------ ------------------
SYS_IL0000063631C00002$$ LOBINDEX
SYS_LOB0000063631C00003$$ LOBSEGMENT
SYS_C009783 INDEX
SYS_IL0000063631C00003$$ LOBINDEX
SYS_LOB0000063631C00002$$ LOBSEGMENT
T TABLE
6 rows selected.

在这个例子中,表本身创建了一个段:如输出中最后一行所示。这里主键约束创建了一个索引段,以保证惟一性。
注意 惟一约束或主键可能创建一个新索引,也可能不创建如果约束列上已经有一个索引,而且这些列处于索引的前几列,这个约束就会(而且将会)使用这些列(而不再创建创建新索引)
另外,每个LOB列分别创建了两个段:一个段用于存储字符大对象(character large object, CLOB)或二进制大对象(binary large object, BLOB)所指的实际数据块,另一个段用于“组织”这些数据块。LOB为非常大块的信息提供了支持,可以多达几GB。LOB存储在lobsegment的块中,lobindex用于跟踪这些LOB块在哪里,以及应该以何种顺序来访问它们。

2.2 段空间管理

管理段空间有两种方法:
1. 手动段空间管理(Manual Segment Space Management):由你设置FREELISTS、FREELIST GROUPS、PCTUSED和其他参数来控制如何分配、使用和重用段中的空间。
2. 自动段空间管理(Automatic Segment Space Management, ASSM):你只需控制与空间使用相关的一个参数:PCTFREE。创建段时也可以接受其他参数,但是这些参数将被忽略。

自动段空间管理是Oracle的遗留实现。它已经存在多年,许多版本都支持MSSM。ASSM则在Oracle 9i Release 1中 才首次引入。原先用于控制空间分配和提供高并发性的参数数不胜数,并且需要对这些参数进行调整,人们不希望还要这么做,这正是设计ASSM的出发点。例如,倘若将FREELISTS参数设置为默认值1,可能会出现,如果你的段是插入/更新新密集的(有大量插入/更新操作),对自由空间的分配就会存在竞争。Oracle要在表中插入一行,或更新一个索引键条目,或者由于更新一行而导致这一行迁移时,可能需要从与这个段 相关的自由块列表中得到一个块。如果只有一个自由块列表,一次就只有一个事务能查看和修改这个列表,事务之间必须相互等待。在这种情况下,如果有多个 FREELISTS和FREELIST GROUPS,就能提高并发性,因为事务可以分别查看不同的列表,而不会相互竞争。
在存储/段特征这方面,应用于ASSM段的存储设置只有:
q BUFFER_POOL
q PCTFREE
q INITRANS
其他存储和物理属性参数都不适用于ASSM段。
段空间管理是从段的表空间(而且段从不会跨表空间)继承来的一个属性。段要使用ASSM,就必须位于支持ASSM空间管理的表空间中。

2.3 高水位线

存储在数据库中的表段使用了这个术语。例如,如果把表想象成一个“平面”结构,或者想象成从左到右依次排开的一系列块,高水平线(high-water mark,HWM)就是包含了数据的最右边的块,

HWM首先位于新创建表的第一个块中。过一段时间后,随着在这个表中放入数据,而且使用了越来越多的块,HWM会升高如果我们删除了表中的一些(甚至全部)行,可能就会有许多块不再包含数据,但是它们仍在HWM之下,而且这些块会一直保持在HWM之下,直到重建、截除或收缩这个对象(将段收缩 是Oracle 10g的一个新特性,只有当段在一个ASSM表空间中时才支持这个特性)

HWM很重要,因为Oracle在全面扫描段时会扫描HWM之下的所有块,即使其中不包含任何数据这会影响全面扫描的性能,特别是当HWM之下的大多数块都为空时。要查看这种情况,只需创建一个有1,000,000行的表(或者创建其他有大量行的表),然后对这个表执行一个SELECT COUNT(*)。 下面再删除(DELETE)这个表中的每一行,你会发现尽管SELECT COUNT(*)统计出0行,但是它与统计出1,000,000所花的时间一样长(如果需要完成块清除,时间可能还会更长)。这是因为Oracle在忙于读取HWM之下的所有块,查看其中是否包含数据。如果对这个表使用TRUNCATE而不是删除其中的每一行,TRUNCATE会把表的HWM重置回“0”,还会截除表上的相关索引。由于以上原因,如果你打算删除表中的所有行,就应该选择使用 TRUNCATE(如果可以使用的话)。

在一个MSSM表空间中,段只有一个HWM。不过,在ASSM表空间中,除了一个HWM外,还有一个低HWM。在MSSM中,HWM推进时 (例如,插入行时),所有块都会并立即有效,Oracle可以安全地读取这些块。不过,对于ASSM,HWM推进时,Oracle并不会立即格式化所有 块,只有在第一次使用这些块时才会完成格式化,以便安全地读取。所以,全面扫描一个段时,必须知道要读取的块是否“安全”或是否格式化。为了避免表中每一个块都必须经过这种安全/不安全检查,Oracle同时维护了一个低HWM和一个HWM。 Oracle会全表扫描至HWM,对于低HWM以下的所有块会直接读取并加以处理。而对介于低HWM和HWM之间的块,则必须更加小心,需要参考管理这些 块所用的ASSM位图信息来查看应该读取哪些块,而哪些块应该被忽略。

2.4 freelists

使用MSSM表空间时,Oracle会在自由列表(freelist)中为有自由空间的对象维护HWM一些的块。
freelists组和freelist组在ASSM表空间中根本就没有;仅MSSM表空间使用这个技术。

每个对象都至少有一个相关的freelist,使用块时,可能会根据需要把块放在freelist上或者从freelist删除。只有位于HWM以下的对象块才会出现在freelist中。仅当freelist为空时才会使用HWM之上的块,此时Oracle会推进HWM,并把这些块增加到freelist中,采用这种方式,Oracle会延迟到不得已时才增加对象的HWM。

一个对象可以有多个freelist。如果预计到会有多个并发用户在一个对象上执行大量的INSERT或UPDATE活动,就可以配置多个freelist,这对性能提升很有好处(但是可能要以额外的存储空间为代价)。根据需要配置足够多的freelist非常重要。
如果存在多个并发的插入和更新,在这样一个环境中,FREELISTS可能对性能产生巨大的影响(可能是促进,也可能是妨碍)。

请考虑下面这个相对简单的表:

scott@ORCL>create tablespace tools
  2  datafile 'D:\app\Administrator\oradata\orcl\tools01.dbf'
  3  size 100m
  4  extent management local
  5  uniform size 128k
  6  segment space management auto
  7  /

表空间已创建。

scott@ORCL>create table t ( x int, y char(50) ) tablespace tools;

表已创建。

接下来使用5个并发会话,开始“疯狂地”对这个表执行插入。如果分别测量插入前和插入后与块相关的系统级等待事件,就会发现长时间的等待,特别是对数据块的 等待(试图插入数据)。这通常是因为表(以及索引)上的freelist不足造成的。为此我使用了 Statspack,首先取一个statspace.snap,接下来执行一个脚本开始5个并发的SQL*Plus会话,等这些会话退出后再取另一个 statspace.snap。这些会话运行的脚本很简单,如下:

begin
	for i in 1 .. 100000
	loop
		insert into t values ( i, 'x' );
	end loop;
	commit; 
end;
/
exit;

这是一个非常简单的代码块,此时我是数据库中惟一的用户。按理说,应该得到最佳的性能,因为我配置了充足的缓冲区缓存,重做日志大小很合适,另外索引也不会 减慢速度,不过,我看到的结果却是:

Top 5 Timed Events                                                    Avg %Total
~~~~~~~~~~~~~~~~~~                                                   wait   Call
Event                                            Waits    Time (s)   (ms)   Time
----------------------------------------- ------------ ----------- ------ ------
CPU time                                                        15          22.3
control file sequential read                     1,294           8      6   12.1
log file switch completion                           9           7    797   10.7
log file parallel write                            132           6     48    9.3
db file sequential read                            106           5     46    7.3

................
                                                             Avg          %Total
                                          %Tim Total Wait   wait    Waits   Call
Event                               Waits  out   Time (s)   (ms)     /txn   Time
---------------------------- ------------ ---- ---------- ------ -------- ------
log file switch completion              9    0          7    797      0.8   10.7
db file sequential read               104    0          5     47      9.5    7.2
read by other session                  75    0          5     64      6.8    7.1
buffer busy waits                   3,991    0          4      1    362.8    6.7

对buffer busy waits总共等待了4秒,也就是每个会话大约1秒。导致这些等待的原因完全是:表中没有配置足够的freelist来应付发生的这种并发活动。

只需将表创建为有多个freelist,就能轻松地消除大部分等待时间:

scott@ORCL>create table t ( x int, y char(50) )
  2  storage( freelists 5 ) tablespace tools;

表已创建。

或者也可以通过修改对象达到目的:

alter table t storage ( FREELISTS 5 );

buffer busy waits大幅下降,而且所需的CPU时间也随着耗用时间的下降而减少(因为这里做的工作更少;对闩定数据结构的竞争确实会让CPU焦头烂额):

Top 5 Timed Events                                                    Avg %Total
~~~~~~~~~~~~~~~~~~                                                   wait   Call
Event                                            Waits    Time (s)   (ms)   Time
----------------------------------------- ------------ ----------- ------ ------
CPU time                                                        18          29.9
control file sequential read                     1,091           6      5   10.1
log file switch (checkpoint incomplete)              3           6   1903    9.7
log file parallel write                            105           5     44    7.9
db file parallel write                             419           4     10    7.3
...............
                                                             Avg          %Total
                                          %Tim Total Wait   wait    Waits   Call
Event                               Waits  out   Time (s)   (ms)     /txn   Time
---------------------------- ------------ ---- ---------- ------ -------- ------
log file switch (checkpoint             3    0          6   1903      0.2    9.7
buffer busy waits                  21,735    0          4      0  1,671.9    6.4
log file switch completion              9    0          3    334      0.7    5.1

对于一个表来说,你可能想确定最多能有多少个真正的并发插入或更新(这需要更多空间)。这里的“真正的并发”是指,你认为两个人在同一时刻请求表中一 个自由块的情况是否频繁。这不是对重叠事务的一种量度;而是量度多少个会话在同时完成插入,而不论事务边界是什么。你可能希望对表的并发插入有多少, freelist就有多少,以此来提高并发性。
使用多个freelist时,有一个主freelist,还有 一些进程freelist。如果一个段只有一个freelist,那么主freelist和进程freelist就是这同一个自由列表。如果你有两个 freelist,实际上将有一个主freelist和两个进程freelist。对于一个给定的会话,会根据其会话ID的散列值为之指定一个进程 freelist。目前,每个进程freelist都只有很少的块,余下的自由块都在主freelist上。使用一个进程freelist时,它会根据需 要从主freelist拉出一些块。如果主freelist无法满足空间需求,Oracle就会推进HWM,并向主freelist中增加空块。过一段时 间后,主freelist会把其存储空间分配多个进程freelist(再次说明,每个进程freelist都只有为数不多的块)。因此,每个进程会使用 一个进程freelist。它不会从一个进程freelist到另一个进程freelist上寻找空间。这说明,如果一个表上有10个进程 freelist,而且你的进程所用的进程freelist已经用尽了该列表中的自由缓冲区,它不会到另一个进程freelist上寻找空间,即使另外9 个进程freelist都分别有5块(总共有45个块),此时它还是会去求助主freelist。假设主freelist上的空间无法满足这样一个自由块 请求,就会导致表推进HWM,或者如果表的HWM无法推进(所有空间都已用),就要扩展表的空间(得到另一个区段)。然后这个进程仍然只使用其 freelist上的空间(现在不再为空)。使用多个freelist时要有所权衡。一方面,使用多个freelist可以大幅度提升性能。另一方面,有 可能导致表不太必要地使用稍多的磁盘空间。

FREELISTS参数,可以根据意愿自由地将其改大或改小。可以把它修改为一个大数,从而与采用传统路径模式的SQL*Loader并行完成数据的加 载。这样可以获得高度并发的加载,而只有最少的等待。加载之后,可以再把这个值降低为某个更合理的平常的数。将空间改小时,现有的多个freelist上 的块要合并为一个主freelist。
要解决前面提到的缓冲区忙等待问题,还有一种方法,这就是使用一个ASSM管理的表空间。还是前面的例子,但在ASSM管理的表空间中要如下创建表T:

scott@ORCL>create tablespace assm
  2  datafile 'D:\app\Administrator\oradata\orcl\assm.dbf' size 1m autoextend on
 next 1m
  3  segment space management auto;

表空间已创建。


scott@ORCL>create table t ( x int, y char(50) ) tablespace ASSM;

表已创建。

在这种情况下,缓冲区忙等待、CPU时间和耗用时间都会下降,在此不必确定最好要有多少个freelist:

Top 5 Timed Events                                                    Avg %Total
~~~~~~~~~~~~~~~~~~                                                   wait   Call
Event                                            Waits    Time (s)   (ms)   Time
----------------------------------------- ------------ ----------- ------ ------
enq: HW - contention                               225          21     92   24.1
CPU time                                                        15          17.9
enq: TX - contention                                51          13    253   15.0
control file sequential read                     1,920           8      4    9.4
Disk file operations I/O                           163           5     33    6.3
          -------------------------------------------------------------
                                                             Avg          %Total
                                          %Tim Total Wait   wait    Waits   Call
Event                               Waits  out   Time (s)   (ms)     /txn   Time
---------------------------- ------------ ---- ---------- ------ -------- ------
enq: HW - contention                  225    0         21     92     28.1   24.1
enq: TX - contention                   51    0         13    253      6.4   15.0
buffer busy waits                   6,299    0          4      1    787.4    5.2

这就是ASSM的主要作用之一:不必手动地确定许多关键存储参数的正确设置

2.5 PCTFREE和PCTUSED

一般而言,PCTFREE参数用来告诉Oracle应该在块上保留多少空间来完成将来的更新。默认情况下,这个值是10%。如果自由空间的百分比高于 PCTFREE中的指定值,这个块就认为是“自由的”。PCTUSED则告诉Oracle当前不“自由”的一个块上自由空间百分比需要达到多大才能使它再 次变为自由的。默认值是40%。
如前所述,对于一个表(而不是一个IOT),PCTFREE会告诉Oracle:块上应该保留多大的空间来完成将来的更新。这说明,如果我们使用的块大小为8KB,只要向块中增加一个新行,就会导致块上的自由空间下降大约800字节,Oracle会使用FREELIST的另一个块,而不是现有的块。块上这10%的数据空间会预留出来,以便更新该块上的行。

实际上PCTUSED的含义是,如果块上不自由的空间到达或小于PCTUSED参数指定的百分比时,这个块将重新变为自由,如倘若PCTUSED为40%,那么块上不自由的空间小于40%时,即自由空间达到60%时,这个块就重新变为自由。

注意 对于不同的表类型,PCTFREE和PCTUSED的实现有所不同。对于某些表类型,这两个参数都要使用,而另外一些表类型只使用PCTFREE,而且对于 这些表类型,仅当创建对象时才会使用PCTFREE。IOT在创建时可以使用PCTFREE在表中预览空间来完成将来的更新,但是在其他方面并不使用 PCTFREE,例如,PCTFREE不用于决定何时停止向一个给定块中插入行。
根 据你使用的是ASSM表空间还是MSSM表空间,这两个参数的实际作用会有所不同。使用MSSM时,这些参数设置控制着块何时放入freelist中,以及何时从freelist中取出。如果使用默认值:PCTFREE为10,PCTUSED为40,那么在块到达90%满之前(有10%以上的自由空间), 这个块会一直在freelist上。一旦到底90%,就会从freelist中取出,而且直到块上的自由空间超过了块的60%时,才会重新回到 freelist上,在此之前,这个块一直不在freelist上。
使用ASSM时,PCTFREE仍然会限制能否将一个新行插入到一个块中,但是它不会控制一个块是否在freelist上,因为ASSM根本不使用freelist。在ASSM中,PCTUSED将被忽略。
PCTFREE有3 种设置:太高、太低、刚好。如果把块的PCTFREE设置得过高,就会浪费空间。如果把PCTFREE设置为50%,而你从未更新数据,那么每个块都会浪 费50%的空间。不过,在另一个表上,50%可能非常合理。如果行初始很小,现在想将行的大小加倍,但是倘若PCTFREE设置得太小,更新行时就会导致 行迁移。

2.5.1 行迁移

行迁移(row migration)是指由于某一行变得太大,无法再与其余的行一同放在创建这一行的块中(块中已经放不下这一行),这就要求这一行离开原来的块

Oracle不能简单地移动这一行,它必须留下一个“转发地址”。Oracle迁移这一行时,它会留下一个指针,指示这一行实际上在什么位置。

因 此,迁移行(migrated row)就是这一行从最初所插入的块上移到另外的某个块上。应用绝对不会知道存在行迁移;使用的SQL也没有任何不同。行迁移 只会影响性能如果你通过一个索引来读这一行,索引会指向原来的块,那个块再指向这个新块。要得到具体的行数据,一般并不是执行两个左右的I/O就可以得到行数据。如果这种行所占的比例相当大,而且有大量用户在访问这些行,访问这些数据的速度开始变慢(额外的I/O以及与I/O相关的闩定都会增加访问时间),缓冲区缓存的效率开始下降(需要缓存两个块,而如果行没有迁移就只需要 缓存一个块),另外表的大小、复杂性都有所增加。
如果一行从左边的块迁移到右边的块,而且它在将来某个时间点还要再迁移,在这一行迁移到的“目标”块上又增加了其他的行,然后这一行再次更新,变得更大。Oracle实际上会把这一行迁移回原来的块,如果有足够的空间,仍放回原地(这么一来,这一行可能变得“未迁移”)。如果没有足够的空间,Oracle会把这一行迁移到另外的某个块上,并修改原来块上的转发地址。 因此,行迁移总是涉及一层间接性。
如果设置得当,PCTFREE 可以帮助你尽量减少行串链。

2.5.2. 设置PCTFREE和PCTUSED值

使用MSSM时,PCTUSED和PCTFREE都很重要;对于 ASSM,只有PCTFREE是重要的。

一方面,使用这些参数来避免迁移过多的行。另一方面,要使用这些参数避免浪费太多的空间。你需要查看对象,描述这些对象要如何使用,然后为设置这些值得出一个逻辑计划。设置这些参数时,必须根据具体的使用设置。可以考虑以 下做法(要记住,这里的“高”和“低”都是相对的;而且使用ASSM时仅PCTFREE适用):
q 高PCTFREE,低PCTUSED:如果你插入了将要更新的大量数据,而且这些更新会频繁地增加行的大小,此时就适合采用这种设置。这种设置在插入后会在块上预留大量的空间(高PCTFREE),并使得将块放回到freelist之前必须几乎为空(低PCTUSED)。
q 低PCTFREE,高PCTUSED:如果你只想对表完成INSERT或DELETE,或者如果确实要完成UPDATE,但UPDATE只是缩小行的大小,此时这种设置就很适合。

2.6 LOGGING和NOLOGGING

通常对象都采用LOGGING方式创建,这说明对象上完成的操作只要能生成redo就都会生成redo。NOLOGGING则允许该对象完成某些操作时可以不生成redo。NOLOGGING只影响几个特定的操作,如对象的初始创建,或使用SQL*Loader的直接路径加载, 或者重建。
这个选项并不会完全禁用对象的重做日志生成,只是几个特定的操作不生成日志而已。例如,如果把一个表创建为SELECT NOLOGGING,然后INSERT INTO THAT_TABLE VALUES(1),这个INSERT就会生成日志,但是表创建可能不生成redo(DBA可以在数据库或表空间级强制生成日志)。

2.7 INITRANS和MAXTRANS

段中每个块都有一个块首部。这个块首部中有一个事务表。事务表中会建立一些条目来描述哪些事务将块上的哪些行/元素锁定。这个事务表的初始大小由对象的 INITRANS设置指定。对于表,这个值默认为2(索引的INITRANS也默认为2)。事务表会根据需要动态扩展,最大达到MAXTRANS个条目 (假设块上有足够的自由空间)。所分配的每个事务条目需要占用块首部中的23~24字节的存储空间。注意,对于Oracle 10g,MAXTRANS则会忽略,所有段的MAXTRANS都是255。

转载于:https://my.oschina.net/u/1862478/blog/1816512

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值