漫长的出差
Posted by 老熊 on 8月 29th, 2008到成都工作以来,最漫长的一次出差。为了处理一个故障,已经出差10来天了,有达到半个月的趋势。不可控的因素,导致这么长时间的出差,虽然比项目实施出差的时间短,但以我们这种工作性质来说算是比较长的了。
看看什么时候会再次打破这个记录。
到成都工作以来,最漫长的一次出差。为了处理一个故障,已经出差10来天了,有达到半个月的趋势。不可控的因素,导致这么长时间的出差,虽然比项目实施出差的时间短,但以我们这种工作性质来说算是比较长的了。
看看什么时候会再次打破这个记录。
下面一条SQL能够使用索引吗?
select object_id,object_name,object_type from t1 where object_id is null;
有人会说,索引不存储null值,所以这个SQL不会使用索引;也有人会说,能够使用索引啊,只要在object_id列上建位图索引就可以使用索引了,另外对于CLUSTER表的KEY列,null值也可以存储在索引中(也就是能够进行索引)。
本文要探讨的是,null值不能进行索引的真正含义:
实际上对于null值,除了位图索引、CLUSTER表的KEY列,也是有可能索引的。那就是复合索引,也就是多列索引。对于普通的索引,null值不能进行索引的正确理解应该是,对于某一行,索引的所有列的值都是null值时,该行才不能被索引。
那么对于上面的SQL语句,我们就可以想办法让它走索引。下面举例说明:
SQL> desc t1
名称 是否为空? 类型
----------------------------------------- -------- --------------
OWNER VARCHAR2(30)
OBJECT_NAME NOT NULL VARCHAR2(128)
SUBOBJECT_NAME VARCHAR2(30)
OBJECT_ID NUMBER
DATA_OBJECT_ID NUMBER
OBJECT_TYPE VARCHAR2(18)
CREATED DATE
LAST_DDL_TIME DATE
TIMESTAMP VARCHAR2(19)
STATUS VARCHAR2(7)
TEMPORARY VARCHAR2(1)
GENERATED VARCHAR2(1)
SECONDARY VARCHAR2(1)SQL> create index t1_idx on t1(object_id,object_name);
SQL> analyze table t1 compute statistics for table for all indexes for all indexed columns;表已分析。
SQL> select object_id,object_name,object_type from t1 where object_id is null;OBJECT_ID OBJECT_NAME OBJECT_TYPE
---------- ------------------------------ ------------------------------
XTY DATABASE LINKExecution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=38)
1 0 TABLE ACCESS (BY INDEX ROWID) OF ‘T1′ (Cost=3 Card=1 Bytes
=38)2 1 INDEX (RANGE SCAN) OF ‘T1_IDX’ (NON-UNIQUE) (Cost=2 Card
=1)
我们可以看到,这个SQL语句走了我们建的那个索引T1_IDX。
然而,如果我们把object_name列改为允许NULL值,那么情况就发生了变化:
SQL>alter table t1 modify (object_name null);
SQL> select object_id,object_name,object_type from t1 where object_id is null;OBJECT_ID OBJECT_NAME OBJECT_TYPE
---------- ------------------------------ ------------------------------
XTY DATABASE LINKExecution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=128 Card=1 Bytes=38)
1 0 TABLE ACCESS (FULL) OF ‘T1′ (Cost=128 Card=1 Bytes=38)
把object_name列改为允许NULL值后,object_id和object_name列 有可能同时为NULL值,这个时候就存在着不被索引的行(就是有可能存在object_id值为null的行没有被索引),这样就只能走全表扫描了。
我们也有一种更简便的方法,不需要与其他列建立复合索引,而是与一个常量值建立复合索引:
SQL> create index t1_idx on t1(object_id,0);
SQL> analyze table t1 compute statistics for table for all indexes for all indexed columns;
SQL> explain plan for select object_id,object_name,object_type from t1 where object_id is null;
已解释。
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 81 | 3 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 1 | 81 | 3 |
|* 2 | INDEX RANGE SCAN | T1_IDX | 1 | | 2 |
---------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------2 - access(”T1″.”OBJECT_ID” IS NULL)
Note: cpu costing is off
引申开来,如果有类似于col_name is null这样的条件的SQL语句,希望能够使用索引,那么将col_name与其他NOT NULL的列或一个常量值建一个复合索引,也是一个可能的选择。
大家在管理ORACLE数据库时,通常使用PROFILE对用户密码设置期限,但是需要注意应用系统连接的用户,对于密码期限设置,应谨慎处理。
首先我们看看怎么样为用户设置密码有效期:
在测试例子中,我们使用TEST用户进行测试,密码为TEST,先看看用户的状态。
SQL> select account_status,lock_date,expiry_date,created,profile from dba_users where username=’TEST’;
ACCOUNT_STATUS LOCK_DATE EXPIRY_DATE CREATED PROFILE
-------------- ---------- ----------- ------------------- -------
OPEN 2008-03-27 15:29:18 DEFAULTSQL> select ctime,ptime,exptime,ltime,spare6 from user$ where name=’TEST’;
CTIME PTIME EXPTIME LTIME SPARE6
------------------- ------------------- ------------------- ------------------- -------------------
2008-03-27 15:29:18 2008-03-27 15:29:18
在user$数据字典中,有几个字段是dba_users中看不到的。比如PTIME(应该就是密码设置或修改的时间),这里PTIME=CREATED(因为用户创建后没有改变过密码)
下面我们将创建profile,将密码有效期设置为10天,并将用户TEST的PROFILE设置为创建的test_profile:
SQL> create profile test_profile limit password_life_time 10 password_grace_time 0;
配置文件已创建
SQL> alter user test profile test_profile;
用户已更改。
再看看用户数据:
SQL> select account_status,lock_date,expiry_date,created,profile from dba_users where username=’TEST’;
ACCOUNT_STATUS LOCK_DATE EXPIRY_DATE CREATED PROFILE
------------------------------ ------------------- ------------------- ------------------- ------------
OPEN 2008-04-06 15:29:18 2008-03-27 15:29:18 TEST_PROFILESQL> select ctime,ptime,exptime,ltime,spare6 from user$ where name=’TEST’;
CTIME PTIME EXPTIME LTIME SPARE6
------------------- ------------------- ------------------- ------------------- -------------------
2008-03-27 15:29:18 2008-03-27 15:29:18
注意到除了PROFILE列从DEFAULT变为了TEST_PROFILE,EXPIRY_DATE改变了,正好是PTIME+10。注意在USER$表中,EXPTIME为空,DBA_USERS中的EXPIRY_TIME是通过PTIME和PROFILE计算出来的。因此EXPIRY_TIME为密码将要到期的时间。
现在为用户设置好了PROFILE,新开一个SQLPLUS会话,用TEST用户登录:
SQL> connect test/test
ERROR:
ORA-28001: the password has expired更改test的口令
新口令:
这个时候可以修改用户的密码。但是如果是应用软件没有对ORA-28001错误进行处理,则不能进行连接。这个时候我们看看用户的状态:
SQL> select account_status,lock_date,expiry_date,created,profile from dba_users where username=’TEST’;
ACCOUNT_STATUS LOCK_DATE EXPIRY_DATE CREATED PROFILE
------------------------------ ------------------- ------------------- ------------------- ------------
EXPIRED 2008-03-27 15:29:18 TEST_PROFILE
SQL> select account_status,lock_date,expiry_date,created,profile from dba_users where username=’TEST’;ACCOUNT_STATUS LOCK_DATE EXPIRY_DATE CREATED PROFILE
------------------------------ ------------------- ------------------- ------------------- ------------
EXPIRED 2008-03-27 15:29:18 TEST_PROFILE
可以看到用户状态为EXPIRED。这个状态是记录在数据字典USER$中的,如果此时把用户的PROFILE改回为DEFAULT,这个状态仍然不会改变。
SQL> alter user test profile default;
用户已更改。
SQL> select account_status,lock_date,expiry_date,created,profile from dba_users where username=’TEST’;
ACCOUNT_STATUS LOCK_DATE EXPIRY_DATE CREATED PROFILE
------------------------------ ------------------- ------------------- ------------------- ------------
EXPIRED 2008-03-27 15:29:18 DEFAULT
用户状态仍然为EXPIRED。这个时候,如果应用连接不上数据库,只有DBA手工干预了。对于状态为LOCKED的用户,使用alter user user_name account unlock即可。对于EXPIRED状态的用户,没有UNEXPIRE的命令,只有通过修改用户密码来重设状态:
SQL> alter user test identified by test;
用户已更改。
SQL> select account_status,lock_date,expiry_date,created,profile from dba_users where username=’TEST’;
ACCOUNT_STATUS LOCK_DATE EXPIRY_DATE CREATED PROFILE
------------------------------ ------------------- ------------------- ------------------- ------------
OPEN 2008-03-27 15:29:18 DEFAULT可以看到用户状态已经恢复正常。
SQL> select ctime,ptime,exptime,ltime,spare6 from user$ where name=’TEST’;
CTIME PTIME EXPTIME LTIME SPARE6
------------------- ------------------- ------------------- ------------------- ------------------
2008-03-27 15:29:18 2008-08-13 23:16:42
用户的密码设置时间也发生了变化。
如果在某些情况下,不知道用户的密码,可以通过下面的办法来设置密码:
SQL> select password from dba_users where username=’TEST’;
PASSWORD
------------------------------
7A0F2B316C212D67SQL> alter user test identified by values ‘7A0F2B316C212D67′;
用户已更改。
总结:对于为用户设置了密码有效期限的用户,应用软件应能够处理ORA-28001错误,或者DBA应定期对密码进行重设。否则不要为用户密码设置期限,当然对于DBA帐号,为安全起见,通过PROFILE强制要求用户定期修改密码,并且可以要求每次使用的密码不能使用以前使用的密码。
虽然大部分时候都是在用Oracle9i,就算用10g,新特性也用得不多,但现在连11g都出来一年了,再这样下去就成老古董啦。所以如今从头把concepts来看,不过这次是10g的版本。数年之前,曾经看过两遍8i的concepts,9i的concepts也读过两遍,看来这10g的concepts只需要一遍就够了。
Oracle的经典书籍何其多,我也仔细看过数本,但我觉得最实在的还是Oracle的官方文档。不管怎么忙,一天至少要看10页,不是简单的看,而是要真正理解。希望从concept这本最经典的书中挖掘出以往不曾注意到的价值。
在上一篇文章(Oracle的段类型 Part I)中,我们得到了Oracle9i中所有的段类型,下面我们将对每一种段类型进行一个简单的说明:
TABLE:这是最常见的段类型,普通表(即非CLUSTER),没有分区,则每个表有一个类型为TABLE的段。
INDEX:这是除了TABLE之外最常见的段类型,表的普通索引,没有分区,则每个索引有一个类型为INDEX的段。除了表上的普通索引之外,INDEX CLUSTER上的索引也是INDEX段,并且在INDEX CLUSTER上必须有一个索引(HASH CLUSTER不要求建索引)。注意IOT表的段类型为INDEX段,而不是TABLE段:
SQL> create table t2 ( object_id number primary key,object_name varchar2(100))
2 organization index;
SQL> select owner,segment_type,segment_name,header_file,header_block from dba_segments where segment_name=’T2′;
未选定行
SQL> select index_name from user_indexes where table_name=’T2′;
INDEX_NAME
------------------------------
SYS_IOT_TOP_29668
SQL> select owner,segment_type,segment_name from dba_segments where segment_name=’SYS_IOT_TOP_29668′;
OWNER SEGMENT_TYPE SEGMENT_NAME
---------- --------------- ----------------------------------------
SYS INDEX SYS_IOT_TOP_29668
注意IOT表的溢出段是TABLE类型的段:
SQL> create table iot
2 ( x int,
3 y date,
4 z varchar2(2000),
5 constraint iot_pk primary key (x)
6 )
7 organization index
8 pctthreshold 10
9 overflow;
表已创建。
SQL> select owner,segment_type,segment_name from dba_segments where owner=’TEST’;
OWNER SEGMENT_TYPE SEGMENT_NAME
---------- --------------- ----------------------------------------
TEST TABLE SYS_IOT_OVER_29670
TEST INDEX IOT_PK
TABLE PARTITION和TABLE SUBPARTITION:表分区,每个分区或子分区都有一个段。
INDEX PARTITION和INDEX SUBPARTITION:索引分区,每个分区或子分区都有一个段。
CLUSTER:每个CLUSTER有一个CLUSTER段。一个CLUSTER中可以存储一个或多个表。由于CLUSTER不能分区,所以没有CLUSTER PARTITION这样的段。
LOBINDEX:表的每个LOB字段,有一个LOBINDEX段。注意对于分区表的LOB字段,每个分区上的LOB字段均会有LOBINDEX段,但是段类型为INDEX PARTITION或INDEX SUBPARTITION,这是一个特殊情况(不知道ORACLE为什么这样,从视图定义上看sys.indpart$和sys.indsubpart$没有type#字段)。
LOBSEGMENT、LOB PARTITION、LOB SUBPARTITION:表中的每个LOB字段,有LOBSEGMENT字段,如果表进行了分区,则在每个分区上相应有LOB PARTITION和LOB SUBPARTITION:
SQL> create table t
2 ( id int primary key,
3 txt clob
4 )
5 /
SQL> select owner,segment_type,segment_name from dba_segments where owner=’TEST’;
OWNER SEGMENT_TYPE SEGMENT_NAME
---------- --------------- ----------------------------------------
TEST TABLE T
TEST LOBINDEX SYS_IL0000029682C00002$$
TEST INDEX SYS_C002632
TEST LOBSEGMENT SYS_LOB0000029682C00002$$
注意:虽然BFILE可以作为LOB类型进行处理,但存储没有LOBINDEX和LOBSEGMENT字段:
SQL> create table t
2 ( id int primary key,
3 thefile bfile
4 )
5 /
SQL> select owner,segment_type,segment_name from dba_segments where owner=’TEST’;
OWNER SEGMENT_TYPE SEGMENT_NAME
---------- --------------- ----------------------------------------
TEST TABLE T
TEST INDEX SYS_C002633
可以看到没有任何与BFILE相关的单独的段。
ROLLBACK:就是8i及以前的回滚段,在9i以及以后的版本中,即使使用了自动撤销段管理,仍然会有一个SYSTEM回滚段。
TYPE2 UNDO:这就是9i及以后的“撤销段”,跟ROLLBACK段类似。我们仍然习惯于叫回滚段。
DEFERRED ROLLBACK:延迟回滚段。如果一个表空间OFFLINE时,表空间上的对象存在活动事务,则会在SYSTEM表空间中创建延迟回滚段,以便在表空间ONLINE能够回滚:
SQL> insert into t select * from dba_objects where rownum<=10;
已创建10行。
SQL> alter tablespace tools offline;
表空间已更改。
SQL> select owner,segment_type,segment_name from dba_segments where segment_type like ‘%DEF%’;
OWNER SEGMENT_TYPE SEGMENT_NAME
---------- ------------------------------ ----------------------------------------
SYS DEFERRED ROLLBACK 1.84337
TEMPORARY:临时段。除了磁盘排序产生临时段之外,临时表也会有临时段。另外,在CTAS过程中,如果SQL还没有最终完成,这个时候的表对应的段为TEMPORARY表,只有在SQL执行的最后将TEMPORARY段改为TABLE段。比如:
SQL> create table t2 as select * from dba_objects;
在执行上面语句的同时,执行:
SQL> select segment_type,owner,segment_name from dba_segments where segment_type=’TEMPORARY’;
SEGMENT_TYPE OWNER SEGMENT_NAME
------------------ ------------------------------ --------------------------------------------
TEMPORARY SYS 1.84337
可以看到临时段,在CTAS执行完之后,我们可以看到:
SQL> select segment_type,owner,segment_name from dba_segments where segment_type=’TEMPORARY’;
未选定行
SQL> select header_file,header_block from dba_segments where owner=USER and segment_name=’T2′;
HEADER_FILE HEADER_BLOCK
----------- ------------
1 84337
可以看到,之前的临时段(其段名为一个特别的名字1.84337,段头的文件号和块号),与CTAS后的表的段头一致。
另外在表和索引的MOVE、REBUILD阶段也会有临时段。所以临时段不一定是在临时表中,在普通的表空间中也可能会存在。
注意在排序段和临时表的段在并没有在DBA_SEGMENTS视图,而是在V$TEMPSEG_USAGE视图中。
CACHE:这是一个特殊的段,为Oracle的自举(bootstrap)段。
SQL> select owner,segment_type,segment_name,header_file,header_block from dba_segments where segment_type=’CACHE’;
OWNER SEGMENT_TYPE SEGMENT_NAME HEADER_FILE HEADER_BLOCK
---------- --------------- --------------- ----------- ------------
SYS CACHE 1.833 1 833
我们通过DUMP数据文件头可以发现:
FILE HEADER:
Software vsn=153092096=0×9200000, Compatibility Vsn=134217728=0×8000000
Db ID=2968647772=0xb0f1f85c, Db Name=’XJ’
Activation ID=0=0×0
Control Seq=761=0×2f9, File size=128000=0×1f400
File Number=1, Blksiz=4096, File Type=3 DATA
Tablespace #0 - SYSTEM rel_fn:1
Creation at scn: 0×0000.00000009 05/12/2002 16:20:42
Backup taken at scn: 0×0000.00000000 01/01/1988 00:00:00 thread:0
reset logs count:0×26ce9ece scn: 0×0000.000a65e0 recovered at 07/19/2008 21:23:10
status:0×4 root dba:0×00400341 chkpt cnt: 272 ctl cnt:271
root dba转换为文件号和块号则为1.833,正好是类型为CACHE的段头。Oracle通过文件号为1的文件头的root dba定位到自举对象,然后得到obj$等核心对象所在位置,来进行启动。
NESTED TABLE:嵌套表的段,以面举例子说明:
SQL> create or replace type emp_type
2 as object
3 (empno number(4),
4 ename varchar2(10),
5 job varchar2(9),
6 mgr number(4)
7 );
8 /
类型已创建。
SQL> create or replace type emp_tab_type
2 as table of emp_type;
3 /
类型已创建。
SQL> create table dept_and_em
2 (deptno number(2) primary key,
3 dname varchar2(14),
4 loc varchar2(13),
5 emps emp_tab_type,
6 emps2 emp_tab_type
7 )
8 nested table emps store as emps_nt
9 nested table emps2 store as emps_nt2;
表已创建。
SQL> select owner,segment_type,segment_name from dba_segments where owner=’TEST’;
OWNER SEGMENT_TYPE SEGMENT_NAME
---------- --------------- ----------------------------------------
TEST NESTED TABLE EMPS_NT
TEST NESTED TABLE EMPS_NT2
TEST TABLE DEPT_AND_EM
TEST INDEX SYS_C002629
TEST INDEX SYS_C002630
TEST INDEX SYS_C002631
这里看到有两个类型为NESTED TABLE的段。另外除了主键之外,每个NESTED TABLE字段上还有一个索引(实际上是每个NESTED TABLE字段对应一具隐含字段,上面建有索引)。
Oracle数据库中有多少类型的段,除了常见的TABLE、INDEX之外还有哪些?下面通过Oracle9i的数据字典来探讨Oracle的段类型。
SQL> select distinct segment_type from dba_segments;
SEGMENT_TYPE
------------------
CACHE
CLUSTER
INDEX
INDEX PARTITION
LOBINDEX
LOBSEGMENT
NESTED TABLE
ROLLBACK
TABLE
TABLE PARTITION
TYPE2 UNDO
然而在DBA_SEGMENTS视图中,不一定包含了所有的段类型,我们从DBA_SEGMENTS的定义中去寻找Oracle的段类型。
SQL> select text from dba_views where view_name=’DBA_SEGMENTS’;
TEXT
----------------------------------------------------------------------------------------------------
select owner, segment_name, partition_name, segment_type, tablespace_name,
header_file, header_block,
dbms_space_admin.segment_number_blocks(tablespace_id, relative_fno,
header_block, segment_type_id, buffer_pool_id, segment_flags,
segment_objd, blocks)*blocksize,
dbms_space_admin.segment_number_blocks(tablespace_id, relative_fno,
header_block, segment_type_id, buffer_pool_id, segment_flags,
segment_objd, blocks),
dbms_space_admin.segment_number_extents(tablespace_id, relative_fno,
header_block, segment_type_id, buffer_pool_id, segment_flags,
segment_objd, extents),
initial_extent, next_extent, min_extents, max_extents, pct_increase,
freelists, freelist_groups, relative_fno,
decode(buffer_pool_id, 0, ‘DEFAULT’, 1, ‘KEEP’, 2, ‘RECYCLE’, NULL)
from sys_dba_segs
SQL> select text from dba_views where view_name=’SYS_DBA_SEGS’;
TEXT
--------------------------------------------------------------------------
select u.name, o.name, o.subname,
so.object_type, s.type#,
ts.ts#, ts.name, ts.blocksize,
f.file#, s.block#,
s.blocks * ts.blocksize, s.blocks, s.extents,
s.iniexts * ts.blocksize,
decode(bitand(ts.flags, 3), 1, to_number(NULL),
s.extsize * ts.blocksize),
s.minexts, s.maxexts,
decode(bitand(ts.flags, 3), 1, to_number(NULL),
s.extpct),
decode(bitand(ts.flags, 32), 32, to_number(NULL),
decode(s.lists, 0, 1, s.lists)),
decode(bitand(ts.flags, 32), 32, to_number(NULL),
decode(s.groups, 0, 1, s.groups)),
s.file#, s.cachehint, NVL(s.spare1,0), o.dataobj#
from sys.user$ u, sys.obj$ o, sys.ts$ ts, sys.sys_objects so, sys.seg$ s,
sys.file$ f
where s.file# = so.header_file
and s.block# = so.header_block
and s.ts# = so.ts_number
and s.ts# = ts.ts#
and o.obj# = so.object_id
and o.owner# = u.user#
and s.type# = so.segment_type_id
and o.type# = so.object_type_id
and s.ts# = f.ts#
and s.file# = f.relfile#
select u.name, un.name, NULL,
decode(s.type#, 1, ‘ROLLBACK’, 10, ‘TYPE2 UNDO’), s.type#,
ts.ts#, ts.name, ts.blocksize, f.file#, s.block#,
s.blocks * ts.blocksize, s.blocks, s.extents,
s.iniexts * ts.blocksize, s.extsize * ts.blocksize, s.minexts,
s.maxexts, s.extpct,
decode(bitand(ts.flags, 32), 32, to_number(NULL),
decode(s.lists, 0, 1, s.lists)),
decode(bitand(ts.flags, 32), 32, to_number(NULL),
decode(s.groups, 0, 1, s.groups)),
s.file#, s.cachehint, NVL(s.spare1,0), un.us#
from sys.user$ u, sys.ts$ ts, sys.undo$ un, sys.seg$ s, sys.file$ f
where s.file# = un.file#
and s.block# = un.block#
and s.ts# = un.ts#
and s.ts# = ts.ts#
and s.user# = u.user#
and s.type# in (1, 10)
and un.status$ != 1
and un.ts# = f.ts#
and un.file# = f.relfile#
union all
select u.name, to_char(f.file#) || ‘.’ || to_char(s.block#), NULL,
decode(s.type#, 2, ‘DEFERRED ROLLBACK’, 3, ‘TEMPORARY’,
4, ‘CACHE’, 9, ‘SPACE HEADER’, ‘UNDEFINED’), s.type#,
ts.ts#, ts.name, ts.blocksize,
f.file#, s.block#,
s.blocks * ts.blocksize, s.blocks, s.extents,
s.iniexts * ts.blocksize,
decode(bitand(ts.flags, 3), 1, to_number(NULL),
s.extsize * ts.blocksize),
s.minexts, s.maxexts,
decode(bitand(ts.flags, 3), 1, to_number(NULL),
s.extpct),
decode(bitand(ts.flags, 32), 32, to_number(NULL),
decode(s.lists, 0, 1, s.lists)),
decode(bitand(ts.flags, 32), 32, to_number(NULL),
decode(s.groups, 0, 1, s.groups)),
s.file#, s.cachehint, NVL(s.spare1,0), s.hwmincr
from sys.user$ u, sys.ts$ ts, sys.seg$ s, sys.file$ f
where s.ts# = ts.ts#
and s.user# = u.user#
and s.type# not in (1, 5, 6, 8, 10)
and s.ts# = f.ts#
and s.file# = f.relfile#
SQL> select text from dba_views where view_name=’SYS_OBJECTS’;
TEXT
--------------------------------------------------------------------------------------
select decode(bitand(t.property, 8192), 8192, ‘NESTED TABLE’, ‘TABLE’), 2, 5,
t.obj#, t.file#, t.block#, t.ts#
from sys.tab$ t
where bitand(t.property, 1024) = 0 /* exclude clustered tables */
union all
select ‘TABLE PARTITION’, 19, 5,
tp.obj#, tp.file#, tp.block#, tp.ts#
from sys.tabpart$ tp
union all
select ‘CLUSTER’, 3, 5,
c.obj#, c.file#, c.block#, c.ts#
from sys.clu$ c
union all
select decode(i.type#, 8, ‘LOBINDEX’, ‘INDEX’), 1, 6,
i.obj#, i.file#, i.block#, i.ts#
from sys.ind$ i
where i.type# in (1, 2, 3, 4, 6, 7, 8, 9)
union all
select ‘INDEX PARTITION’, 20, 6,
ip.obj#, ip.file#, ip.block#, ip.ts#
from sys.indpart$ ip
union all
select ‘LOBSEGMENT’, 21, 8,
l.lobj#, l.file#, l.block#, l.ts#
from sys.lob$ l
union all
select ‘TABLE SUBPARTITION’, 34, 5,
tsp.obj#, tsp.file#, tsp.block#, tsp.ts#
from sys.tabsubpart$ tsp
union all
select ‘INDEX SUBPARTITION’, 35, 6,
isp.obj#, isp.file#, isp.block#, isp.ts#
from sys.indsubpart$ isp
union all
select decode(lf.fragtype$, ‘P’, ‘LOB PARTITION’, ‘LOB SUBPARTITION’),
decode(lf.fragtype$, ‘P’, 40, 41), 8,
lf.fragobj#, lf.file#, lf.block#, lf.ts#
from sys.lobfrag$ lf
因此,从以上几个视图的定义中可以看到,Oracle9i中有如下的段类型:
NESTED TABLE
TABLE
TABLE PARTITION
CLUSTER
LOBINDEX
INDEX
INDEX PARTITION
LOBSEGMENT
TABLE SUBPARTITION
INDEX SUBPARTITION
LOB PARTITION
LOB SUBPARTITION
ROLLBACK
TYPE2 UNDO
DEFERRED ROLLBACK
TEMPORARY
CACHE
SPACE HEADER
UNDEFINED
Recent Comments