表空间、域索引、位图索引杂烩

表空间存储参数设置
~~~~~~~~~~~~~~
create tablespace local
      datafile '/tmp/local.dbf' size 10M
      default storage
      (initial 100K next 1024K maxextents 120 pctincrease 0);


SQL> SELECT Tablespace_Name,
  2         Extent_Management,
  3         Segment_Space_Management,
  4         Allocation_Type,
  5         Initial_Extent,
  6         Next_Extent
  7    FROM dba_tablespaces
  8   WHERE Tablespace_Name IN ('TEST_TBS','LOCAL');

TABLESPACE_NAME                EXTENT_MAN SEGMEN ALLOCATIO INITIAL_EXTENT NEXT_EXTENT
------------------------------ ---------- ------ --------- -------------- -----------
LOCAL                          LOCAL      MANUAL SYSTEM             65536
TEST_TBS                       LOCAL      MANUAL SYSTEM             65536

--没有指定区管理方式,但是设置了默认存储,这里将使用是
默认的LOCAL管理方式
MSSM
AUTOALLOCATION(initial=64k,next=失效)

SQL> create tablespace local1                                  
  datafile '/tmp/local1.dbf' size 10M                      
  extent management local                                
  default storage                                        
  (initial 100K next 1024K maxextents 120 pctincrease 0);

  2    3    4    5  create tablespace local1
*
ERROR at line 1:
ORA-25143: default storage clause is not compatible with allocation policy

你不能在本地管理的统一管理&自动分配管理下设置默认存储
如果是本地管理,但是是手动段管理,那么你可以在该表空间下创建对象时指定PCTFREE,PCTUSED
 
字典管理表空间
~~~~~~~~~~~~~~

SQL> create tablespace test_dt                 
  2  datafile '/tmp/test_dt.dbf' size 1m reuse 
  3  autoextend on next 1m                     
  4  extent management dictionary              
  5  /
create tablespace test_dt
*
ERROR at line 1:
ORA-12913: Cannot create dictionary managed tablespace

create table t1 ( x number ) tablespace local;
SQL> exec dbms_space_admin.tablespace_migrate_from_local('LOCAL');
BEGIN dbms_space_admin.tablespace_migrate_from_local('LOCAL'); END;

*
ERROR at line 1:
ORA-12914: Cannot migrate tablespace to dictionary managed type
ORA-06512: at "SYS.DBMS_SPACE_ADMIN", line 0
ORA-06512: at line 1


SQL> alter tablespace local read only;

Tablespace altered.

exec dbms_space_admin.tablespace_migrate_from_local('LOCAL');
ERROR at line 1:
ORA-12914: Cannot migrate tablespace to dictionary managed type
ORA-06512: at "SYS.DBMS_SPACE_ADMIN", line 0
ORA-06512: at line 1


SQL> exec dbms_space_admin.tablespace_migrate_from_local('SYSTEM');
BEGIN dbms_space_admin.tablespace_migrate_from_local('SYSTEM'); END;

*
ERROR at line 1:
ORA-03251: Cannot issue this command on SYSTEM tablespace
ORA-06512: at "SYS.DBMS_SPACE_ADMIN", line 0
ORA-06512: at line 1


create table test_dict (chr char(2000)) tablesapce testing;
insert into test_dict select 'test' from dba_objects where rownum <=17;

col Segment_Name format a20
select Segment_Name,Extent_Id,blocks, bytes/1024/1024 sum_blks
  from user_extents 
 where segment_name = 'TEST_DICT';
 
 

1 create table t
2 storage( initial 64k next 64k pctincrease 0 )
3 tablespace testing
4 as
5 select * from all_objects where 1=0;

variable n number;
exec :n := 5;

1 insert into t
2 select * from all_objects where rownum < :n;

set autotrace traceonly statistics;


exec :n := 99999
1 insert into t
2 select * from all_objects where rownum < :n;

set autotrace off
 
本地管理表空间
~~~~~~~~~~~~~~
1 create tablespace testing_lmt
2 datafile '/tmp/testing_lmt.dbf' size 1m reuse
3 autoextend on next 1m
4 extent management local
5 uniform size 64k
6 /


create table test_lmt (chr char(2000)) tablespace testing_lmt;
insert into test_lmt select ' ' from dba_objects where rownum <=17;

col Segment_Name format a20
select Segment_Name,Extent_Id,blocks, bytes/1024/1024 sum_blks
  from user_extents 
 where segment_name = 'TEST_LMT';

commit;


drop table t;

1 create table t
2 tablespace testing_lmt
3 as
4 select * from all_objects where 1=0;

variable n number;
exec :n := 5;

1 insert into t
2 select * from all_objects where rownum < :n;

set autotrace traceonly statistics;


exec :n := 99999
1 insert into t
2 select * from all_objects where rownum < :n;

set autotrace off




查看表空间使用情况
~~~~~~~~~~~~~~~~
表空间
select nvl(b.tablespace_name,
             nvl(a.tablespace_name,'UNKOWN')) name,
       kbytes_alloc kbytes,
       kbytes_alloc-nvl(kbytes_free,0) used,
       nvl(kbytes_free,0) free,
       ((kbytes_alloc-nvl(kbytes_free,0))/
                          kbytes_alloc)*100 pct_used,
       nvl(largest,0) largest
from ( select sum(bytes)/1024 Kbytes_free,
              max(bytes)/1024 largest,
              tablespace_name
       from  sys.dba_free_space
       group by tablespace_name ) a,
     ( select sum(bytes)/1024 Kbytes_alloc,
              tablespace_name
       from sys.dba_data_files
       group by tablespace_name )b
where a.tablespace_name (+) = b.tablespace_name
 

表空间测试
~~~~~~~~~~~~~~
create tablespace test_tbs                   
datafile '/tmp/test_tbs.dbf' size 1m reuse; 

--没有任何区分配方式和段管理方式
SQL> SELECT Tablespace_Name,
  2         Extent_Management,
  3         Segment_Space_Management,
  4         Allocation_Type,
  5         Initial_Extent,
  6         Next_Extent
  7    FROM dba_tablespaces
  8   WHERE Tablespace_Name IN ('TEST_TBS','SYSTEM');

TABLESPACE_NAME                EXTENT_MAN SEGMEN ALLOCATIO INITIAL_EXTENT NEXT_EXTENT
------------------------------ ---------- ------ --------- -------------- -----------
SYSTEM                         LOCAL      MANUAL SYSTEM             65536
TEST_TBS                       LOCAL      MANUAL SYSTEM             65536

我们看到SYSTEM是本地管理方式
9I默认不设置任何区分配方式和段管理方式时是
LOCAL
MSSM
AUTOALLOCATION(initial=64k,next=失效)

SQL> COL FILE_NAME FORMAT A30
SQL> SELECT FILE_NAME,  BYTES,  USER_BYTES ,AUTOEXTENSIBLE        
  2    FROM dba_data_files                            
  3   WHERE Tablespace_Name ='TEST_TBS';   

FILE_NAME                           BYTES USER_BYTES AUT
------------------------------ ---------- ---------- ---
/tmp/test_tbs.dbf                 1048576     983040 NO

1048576 - 983040 = 64K
这64K是文件头保留区域
1048576 + 63*1024 = 1113088

SQL> SELECT tablespace_name,
  2        block_id,
  3        bytes,
  4        blocks
  5   FROM dba_free_space
  6  WHERE tablespace_name = 'TEST_TBS'
  7  /

TABLESPACE_NAME                  BLOCK_ID      BYTES     BLOCKS
------------------------------ ---------- ---------- ----------
TEST_TBS                                9     983040        120


SQL> alter database datafile '/tmp/test_tbs.dbf' resize 1113088;
  
Database altered.
  
这样,在本地管理统一管理的话可能用不到这63K,浪费了空间


本地管理系统分配区测试
~~~~~~~~~~~~~~~
SQL>   select tablespace_name,
  2           block_id,
  3           bytes,
  4           blocks
  5      from dba_free_space
  6     where tablespace_name = 'TEST_TBS'
  7  /

TABLESPACE_NAME                  BLOCK_ID      BYTES     BLOCKS
------------------------------ ---------- ---------- ----------
TEST_TBS                                9     983040        120

初始时,数据文件里没有对象时,在块大小小于16K的时候,文件头保留64K的数据,用于本地区管理
所以空闲区的第1个块号是9号,共可以存放120块

SQL>create table t_t1 ( x int )
  2 storage ( initial 1k next 1k pctincrease 50 )
  3 tablespace test_tbs;
    
Table created.

SQL> SELECT SEGMENT_NAME,
  2         TABLESPACE_NAME,
  3         BLOCK_ID,
  4         BLOCKS,
  5         BYTES
  6    FROM dba_extents
  7   WHERE TABLESPACE_NAME = 'TEST_TBS';

SEGMENT_NA TABLESPACE_NAME                  BLOCK_ID     BLOCKS      BYTES
---------- ------------------------------ ---------- ---------- ----------
T_T1       TEST_TBS                                9          8      65536

SQL> SELECT Segment_Name,Initial_Extent,Min_Extents,Next_Extent FROM dba_segments WHERE segment_name = 'T_T1';

SEGMENT_NAME          INITIAL_EXTENT MIN_EXTENTS NEXT_EXTENT
--------------------- -------------- ----------- -----------
T_T1                           16384           1

我们看到initial 1k,但实际上用了表空间的最小的区INITIAL至少是2个块=16K
这里看不到NEXT EXTENT
 
SQL>  select tablespace_name,
  2          block_id,
  3          bytes,
  4          blocks
  5     from dba_free_space
  6    where tablespace_name = 'TEST_TBS'
  7  /

TABLESPACE_NAME                  BLOCK_ID      BYTES     BLOCKS
------------------------------ ---------- ---------- ----------
TEST_TBS                               17     917504        112

--创建任何一个对象,都需要第1个区,所以,第2组8块被T_T1使用了,所以空闲块从17开始


         
SQL> insert into t_t1  select rownum from dba_objects;  

28516 rows created.

SQL> SELECT SEGMENT_NAME,
  2         TABLESPACE_NAME,
  3         BLOCK_ID,
  4         BLOCKS,
  5         BYTES
  6    FROM dba_extents
  7   WHERE TABLESPACE_NAME = 'TEST_TBS';

SEGMENT_NA TABLESPACE_NAME                  BLOCK_ID     BLOCKS      BYTES
---------- ------------------------------ ---------- ---------- ----------
T_T1       TEST_TBS                                9          8      65536
T_T1       TEST_TBS                               17          8      65536
T_T1       TEST_TBS                               25          8      65536
T_T1       TEST_TBS                               33          8      65536
T_T1       TEST_TBS                               41          8      65536
T_T1       TEST_TBS                               49          8      65536

我们看到没有提交就已经分配了6个8块64K的区

SQL> select tablespace_name,                 
  2         block_id,                        
  3         bytes,                           
  4         blocks                           
  5    from dba_free_space                   
  6   where tablespace_name = 'TEST_TBS'     
  7  
SQL> /

TABLESPACE_NAME                  BLOCK_ID      BYTES     BLOCKS
------------------------------ ---------- ---------- ----------
TEST_TBS                               57     589824         72

我们看到空闲区是从49+8=57的位置


SQL> commit;

Commit complete.
         
SQL> create table t_t2 ( x int ) pctfree 0 initrans 1 
  2   storage ( initial 1k next 1k pctincrease 50 )   
  3   tablespace test_tbs;                            

Table created.

SQL> SELECT SEGMENT_NAME,                 
  2         TABLESPACE_NAME,              
  3         BLOCK_ID,                     
  4         BLOCKS,                       
  5         BYTES                         
  6    FROM dba_extents                   
  7   WHERE TABLESPACE_NAME = 'TEST_TBS'; 

SEGMENT_NA TABLESPACE_NAME                  BLOCK_ID     BLOCKS      BYTES
---------- ------------------------------ ---------- ---------- ----------
T_T1       TEST_TBS                                9          8      65536
T_T1       TEST_TBS                               17          8      65536
T_T1       TEST_TBS                               25          8      65536
T_T1       TEST_TBS                               33          8      65536
T_T1       TEST_TBS                               41          8      65536
T_T1       TEST_TBS                               49          8      65536
T_T2       TEST_TBS                               57          8      65536

7 rows selected.

这里T_T2从57开始分配了8块64K的区


SQL> insert into t_t2  select rownum from dba_objects;  

28516 rows created.

SQL> commit;

Commit complete.
SQL> commit;

Commit complete.

SQL> SELECT SEGMENT_NAME,                 
  2         TABLESPACE_NAME,              
  3         BLOCK_ID,                     
  4         BLOCKS,                       
  5         BYTES                         
  6    FROM dba_extents                   
  7   WHERE TABLESPACE_NAME = 'TEST_TBS'; 

SEGMENT_NA TABLESPACE_NAME                  BLOCK_ID     BLOCKS      BYTES
---------- ------------------------------ ---------- ---------- ----------
T_T1       TEST_TBS                                9          8      65536
T_T1       TEST_TBS                               17          8      65536
T_T1       TEST_TBS                               25          8      65536
T_T1       TEST_TBS                               33          8      65536
T_T1       TEST_TBS                               41          8      65536
T_T1       TEST_TBS                               49          8      65536

T_T2       TEST_TBS                               57          8      65536
T_T2       TEST_TBS                               65          8      65536
T_T2       TEST_TBS                               73          8      65536
T_T2       TEST_TBS                               81          8      65536
T_T2       TEST_TBS                               89          8      65536

11 rows selected.

我们看到同样28516行记录,T_T1用了6个区,T_T2用了5个区,为什么呢

SQL> SELECT TABLE_NAME,PCT_FREE,PCT_USED FROM USER_TABLES WHERE TABLE_NAME IN ('T_T1','T_T2')
  2  /

TABLE_NAME                       PCT_FREE   PCT_USED
------------------------------ ---------- ----------
T_T1                                   10         40
T_T2                                    0         40

原来T_T2更精简,因为PCTFREE=0

SQL> select tablespace_name,             
  2         block_id,                    
  3         bytes,                       
  4         blocks                       
  5    from dba_free_space               
  6   where tablespace_name = 'TEST_TBS' 
  7  
SQL> /

TABLESPACE_NAME                  BLOCK_ID      BYTES     BLOCKS
------------------------------ ---------- ---------- ----------
TEST_TBS                               97     262144         32

现在空闲空间只剩下32块了,正好4个区

SQL>  delete from t_t1 where rownum <=28516/5;

5703 rows deleted.

commit;

SQL> SELECT SEGMENT_NAME,                 
  2         TABLESPACE_NAME,              
  3         BLOCK_ID,                     
  4         BLOCKS,                       
  5         BYTES                         
  6    FROM dba_extents                   
  7   WHERE TABLESPACE_NAME = 'TEST_TBS'; 

SEGMENT_NA TABLESPACE_NAME                  BLOCK_ID     BLOCKS      BYTES
---------- ------------------------------ ---------- ---------- ----------
T_T1       TEST_TBS                                9          8      65536
T_T1       TEST_TBS                               17          8      65536
T_T1       TEST_TBS                               25          8      65536
T_T1       TEST_TBS                               33          8      65536
T_T1       TEST_TBS                               41          8      65536
T_T1       TEST_TBS                               49          8      65536
T_T2       TEST_TBS                               57          8      65536
T_T2       TEST_TBS                               65          8      65536
T_T2       TEST_TBS                               73          8      65536
T_T2       TEST_TBS                               81          8      65536
T_T2       TEST_TBS                               89          8      65536

11 rows selected.

我们看到删除T_T1,空间仍然没有腾出来.

我们来单独分配4个区,使得文件填满,没有空闲分区
SQL> alter table t_t1 allocate extent;

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /        
              
Table altered.


SQL>  SELECT SEGMENT_NAME,                 
  2          TABLESPACE_NAME,              
  3          BLOCK_ID,                     
  4          BLOCKS,                       
  5          BYTES                         
  6     FROM dba_extents                   
  7    WHERE TABLESPACE_NAME = 'TEST_TBS'; 

SEGMENT_NA TABLESPACE_NAME                  BLOCK_ID     BLOCKS      BYTES
---------- ------------------------------ ---------- ---------- ----------
T_T1       TEST_TBS                                9          8      65536
T_T1       TEST_TBS                               17          8      65536
T_T1       TEST_TBS                               25          8      65536
T_T1       TEST_TBS                               33          8      65536
T_T1       TEST_TBS                               41          8      65536
T_T1       TEST_TBS                               49          8      65536
T_T1       TEST_TBS                               97          8      65536 <<-
T_T1       TEST_TBS                              105          8      65536 <<-
T_T1       TEST_TBS                              113          8      65536 <<-
T_T1       TEST_TBS                              121          8      65536 <<-
T_T2       TEST_TBS                               57          8      65536
T_T2       TEST_TBS                               65          8      65536
T_T2       TEST_TBS                               73          8      65536
T_T2       TEST_TBS                               81          8      65536
T_T2       TEST_TBS                               89          8      65536

新增4个区
SQL> select tablespace_name,               
  2         block_id,                      
  3         bytes,                         
  4         blocks                         
  5    from dba_free_space                 
  6   where tablespace_name = 'TEST_TBS'   
  7  /

no rows selected

文件没有空闲空间

--我们看到数据文件没有空间

SQL> alter database datafile '/tmp/test_tbs.dbf' resize 12m;

Database altered.

SQL> col file_name format a30                              
SQL> SELECT FILE_NAME,  BYTES,  USER_BYTES ,AUTOEXTENSIBLE 
  2    FROM dba_data_files                                 
  3   WHERE Tablespace_Name ='TEST_TBS';                   

FILE_NAME                           BYTES USER_BYTES AUT
------------------------------ ---------- ---------- ---
/tmp/test_tbs.dbf                12582912   12517376 NO

SQL> select tablespace_name,           
  2        block_id,                   
  3        bytes,                      
  4        blocks                      
  5   from dba_free_space              
  6  where tablespace_name = 'TEST_TBS'
  7  
SQL> /

TABLESPACE_NAME                  BLOCK_ID      BYTES     BLOCKS
------------------------------ ---------- ---------- ----------
TEST_TBS                              129   11534336       1408

多出了1408个块
SQL> INSERT INTO T_T2 SELECT ROWNUM FROM DBA_OBJECTS;

28516 rows created.

SQL> INSERT INTO T_T2 SELECT * FROM T_T2;

57032 rows created.

SQL> set pagesize 100
SQL> SELECT SEGMENT_NAME,                       
  2         TABLESPACE_NAME,                    
  3         BLOCK_ID,                           
  4         BLOCKS,                             
  5         BYTES                               
  6    FROM dba_extents                         
  7   WHERE TABLESPACE_NAME = 'TEST_TBS';       

SEGMENT_NA TABLESPACE_NAME                  BLOCK_ID     BLOCKS      BYTES
---------- ------------------------------ ---------- ---------- ----------
T_T1       TEST_TBS                                9          8      65536
T_T1       TEST_TBS                               17          8      65536
T_T1       TEST_TBS                               25          8      65536
T_T1       TEST_TBS                               33          8      65536
T_T1       TEST_TBS                               41          8      65536
T_T1       TEST_TBS                               49          8      65536
T_T1       TEST_TBS                               97          8      65536
T_T1       TEST_TBS                              105          8      65536
T_T1       TEST_TBS                              113          8      65536
T_T1       TEST_TBS                              121          8      65536
T_T2       TEST_TBS                               57          8      65536
T_T2       TEST_TBS                               65          8      65536
T_T2       TEST_TBS                               73          8      65536
T_T2       TEST_TBS                               81          8      65536
T_T2       TEST_TBS                               89          8      65536
T_T2       TEST_TBS                              129          8      65536
T_T2       TEST_TBS                              137          8      65536
T_T2       TEST_TBS                              145          8      65536
T_T2       TEST_TBS                              153          8      65536
T_T2       TEST_TBS                              161          8      65536
T_T2       TEST_TBS                              169          8      65536
T_T2       TEST_TBS                              177          8      65536
T_T2       TEST_TBS                              185          8      65536
T_T2       TEST_TBS                              193          8      65536
T_T2       TEST_TBS                              201          8      65536
T_T2       TEST_TBS                              209          8      65536
T_T2       TEST_TBS                              265        128    1048576 <<===T_T2的第17个区就自动扩展成128个块,1M

但是注意,该区需要16个位图来表示这个区

SQL> select tablespace_name,              
  2        block_id,                      
  3        bytes,                         
  4        blocks                         
  5   from dba_free_space                 
  6  where tablespace_name = 'TEST_TBS'   
  7  
SQL> /

TABLESPACE_NAME                  BLOCK_ID      BYTES     BLOCKS
------------------------------ ---------- ---------- ----------
TEST_TBS                              217     393216         48
TEST_TBS                              393    9371648       1144

T_T2扩展到第16个区一直分配到217,在分配第17个区时需要扫描128个块的区,这时候没有直接从217块开始分配,而是预留给48个块
因为48块是适合小的区,防备将来新增小表
从217 + 48 = 265 到393分配给T_T2


SQL> COMMIT;

Commit complete.

create table t_t3 ( x int ) pctfree 0
storage ( initial 1k next 1k pctincrease 50 ) 
tablespace test_tbs;                          

SQL>  SELECT SEGMENT_NAME,
        TABLESPACE_NAME,
        BLOCK_ID,
        BLOCKS,
        BYTES
   FROM dba_extents
  WHERE TABLESPACE_NAME = 'TEST_TBS' AND SEGMENT_NAME = 'T_T3'
  2    3    4    5    6    7    8  /

SEGMENT_NA TABLESPACE_NAME                  BLOCK_ID     BLOCKS      BYTES
---------- ------------------------------ ---------- ---------- ----------
T_T3       TEST_TBS                              217          8      65536

我们看到新表T_T3是从空出来的48块中进行分配

SQL> select tablespace_name,            
  2        block_id,                    
  3        bytes,                       
  4        blocks                       
  5   from dba_free_space               
  6  where tablespace_name = 'TEST_TBS' 
  7  /

TABLESPACE_NAME                  BLOCK_ID      BYTES     BLOCKS
------------------------------ ---------- ---------- ----------
TEST_TBS                              225     327680         40
TEST_TBS                              393    9371648       1144

我们模拟INERT T_T2把1144块填充,大概需要扩展9次
128*8=1024

SQL> INSERT INTO T_T2 SELECT * FROM T_T2;

114064 rows created.

SQL> commit;

Commit complete.

SQL> INSERT INTO T_T2 SELECT * FROM T_T2;

228128 rows created.

SQL> INSERT INTO T_T2 SELECT * FROM T_T2;

456256 rows created.

SQL> commit;

Commit complete.

SQL> select tablespace_name,            
  2        block_id,                    
  3        bytes,                       
  4        blocks                       
  5   from dba_free_space               
  6  where tablespace_name = 'TEST_TBS' 
  7  
SQL> /

TABLESPACE_NAME                  BLOCK_ID      BYTES     BLOCKS
------------------------------ ---------- ---------- ----------
TEST_TBS                              225     327680         40
TEST_TBS                             1417     983040        120

SQL> alter table t_t3 allocate extent;   --15下,正好用完120,因为15*8=120 


Table altered.

SQL> SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.

SQL> /

Table altered.
 

SQL> select tablespace_name,           
  2        block_id,                   
  3        bytes,                      
  4        blocks                      
  5   from dba_free_space              
  6  where tablespace_name = 'TEST_TBS'
  7  /

TABLESPACE_NAME                  BLOCK_ID      BYTES     BLOCKS
------------------------------ ---------- ---------- ----------
TEST_TBS                             1497     327680         40

SQL> SELECT SEGMENT_NAME,
       TABLESPACE_NAME,
       BLOCK_ID,
       BLOCKS,
       BYTES
  FROM dba_extents
 WHERE TABLESPACE_NAME = 'TEST_TBS' AND SEGMENT_NAME = 'T_T3';
  2    3    4    5    6    7  
SEGMENT_NA TABLESPACE_NAME                  BLOCK_ID     BLOCKS      BYTES
---------- ------------------------------ ---------- ---------- ----------
T_T3       TEST_TBS                              217          8      65536
T_T3       TEST_TBS                              225          8      65536
T_T3       TEST_TBS                              233          8      65536
T_T3       TEST_TBS                              241          8      65536
T_T3       TEST_TBS                              249          8      65536
T_T3       TEST_TBS                              257          8      65536
T_T3       TEST_TBS                             1417          8      65536
T_T3       TEST_TBS                             1425          8      65536
T_T3       TEST_TBS                             1433          8      65536
T_T3       TEST_TBS                             1441          8      65536
T_T3       TEST_TBS                             1449          8      65536
T_T3       TEST_TBS                             1457          8      65536
T_T3       TEST_TBS                             1465          8      65536
T_T3       TEST_TBS                             1473          8      65536
T_T3       TEST_TBS                             1481          8      65536
T_T3       TEST_TBS                             1489          8      65536

16个区了,下一个区就是128块

SQL> alter table t_t3 allocate extent;    
alter table t_t3 allocate extent
*
ERROR at line 1:
ORA-01653: unable to extend table SYS.T_T3 by 128 in tablespace TEST_TBS

提示128  in tablespace TEST_TBS

       GIG     CUMGIG    EXTENTS     MBYTES  START_EXT    END_EXT    EXTENTS
---------- ---------- ---------- ---------- ---------- ---------- ----------
    9.9375 .000976563        342      .0625          0         15         16
    9.9375      .0625        342          1         16         78         63
    9.9375          1        342          8         79        198        120
    9.9375     9.9375        342         64        199        341        143
    
二、本地自动extent管理方式
前面讲述了表空间的统一分配,那么,再看看表空间在自动分配情况下是否有碎片。在自动分配的本地管理的表空间中,区间尺寸可能由64KB、1MB、8MB、64MB甚至是256MB等尺寸组成。但是不管尺寸有多大,都有一个通用尺寸64KB,所以64KB就是该表空间的位图(bit)大小。      
在这种方式下,每个位图(1或0)只代表64Kb的基本空间,而不代表统一管理方式中的一个extent大小(uniform size)。
一定程度上存在跟字典管理中同样的问题。如一个extent大小可以等于多个位图,如果表空间中存在很多比较小的连续空间,如64Kb、128kb,那么申请比较大的extent的时候,一样也是申请不了的。
所以,在用户的表空间中,不建议使用自动分配,还是采用统一尺寸分配。
比如,有一个表空间,上面有十个数据文件,每个数据文件还剩500MB的空间,但是,现在有一个段突然需要分配512MB的空间,一样会导致空间分配失败。
不过,自动分配也不是一无是处。应当看到,系统表空间就是自动分配,而且还非常适合,因为:
1,每个对象都不大,但是对象非常多,这样的情况下,如果统一分配,可能造成空间的浪费。而自动分配的基数是64KB,比较节省空间。
2,这些对象基本都不被删除与添加,也就是结构比较稳定。
3,新创建的对象,不指定初始大小,方便使用空间空间。
如果你的业务也满足如上的条件,其实,也完全可以使用自动分配,因为这样可以节省很多空闲空间,也不会有空间碎片产生。

    

字典管理碎片测试
SQL> select *                                                            
  2    from dba_free_space                                               
  3   where bytes <= ( select min(next_extent)                           
  4              from dba_segments                                       
  5             where tablespace_name = dba_free_space.tablespace_name)  
  6     and tablespace_name = 'TEST_TBS'                                 
  7   order by block_id;                                                 


SELECT a.SEGMENT_NAME, a.SEGMENT_TYPE, a.TABLESPACE_NAME, a.OWNER 
    FROM DBA_SEGMENTS a
    WHERE a.NEXT_EXTENT >= (SELECT MAX(b.BYTES)
        FROM DBA_FREE_SPACE b
        WHERE b.TABLESPACE_NAME = a.TABLESPACE_NAME)
    OR a.EXTENTS = a.MAX_EXTENTS
    OR a.EXTENTS = 'data_block_size' ;

本地管理区统一分配
~~~~~~~~~~~~~~
一、本地统一尺寸的extent管理方式:
这种管理方式下,在表空间头部的位图中,用0与1来表示未用的或者已经使用过的空间。1表示已使用,0表示未使用。
下面这个例子,先创建一个本地管理的表空间,extent大小为1MB
create tablespace test_uniform            
datafile '/tmp/test_uniform.dbf' size 10M 
extent management local uniform size 1M;  

SQL>   select tablespace_name,
  2           block_id,
  3           bytes,
  4           blocks
  5      from dba_free_space
  6     where tablespace_name = 'TEST_UNIFORM';

TABLESPACE_NAME                  BLOCK_ID      BYTES     BLOCKS
------------------------------ ---------- ---------- ----------
TEST_UNIFORM                            9    9437184       1152

然后创建一个表,指定初始大小与NEXT大小都是8MB

SQL>  create table test(x number) tablespace TEST_UNIFORM 
  2   storage (initial 8M next 8M);                       

Table created.

虽然取消了NEXT参数,但是,如果指定了NEXT参数,也不会出现任何错误,只是oracle在这里忽略了这个参数。
表创建完成之后,查看他的实际大小与NEXT大小:  


SQL>  select table_name,initial_extent,next_extent from user_tables 
  2   where table_name='TEST'
  3  /

TABLE_NAME                     INITIAL_EXTENT NEXT_EXTENT
------------------------------ -------------- -----------
TEST                                  8388608     1048576

我们这里看到NEXT_EXTENT有值,而且没有按照表的定义设置大小,而在系统自动分配区的情况下该值为空

可以看到,初始区间的确是8MB,但是,NEXT大小是1MB,并不是我们指定的8MB,那么,初始区间的8MB,到底是几个Extent呢?

SELECT SEGMENT_NAME,                 
       TABLESPACE_NAME,              
       BLOCK_ID,                     
       BLOCKS,                       
       BYTES                         
  FROM dba_extents                   
 WHERE segment_name='TEST';   


SQL>   2    3    4    5    6    7 
SEGMENT_NA TABLESPACE_NAME                  BLOCK_ID     BLOCKS      BYTES
---------- ------------------------------ ---------- ---------- ---------- 
TEST       TEST_UNIFORM                            9        128    1048576
TEST       TEST_UNIFORM                          137        128    1048576
TEST       TEST_UNIFORM                          265        128    1048576
TEST       TEST_UNIFORM                          393        128    1048576
TEST       TEST_UNIFORM                          521        128    1048576
TEST       TEST_UNIFORM                          649        128    1048576
TEST       TEST_UNIFORM                          777        128    1048576
TEST       TEST_UNIFORM                          905        128    1048576

从上图可以看到所有区还是1M来分的,即使初始区设置了8M

可以发现,实际上有8个extent,既然是8个不同的extent,那么,他们就可以是不连续的物理空间,且只需要有8个标准尺寸的1MB空间就可以了。
根据以上的原理,每个段的extent大小都等于表空间的统一尺寸大小,所以,根本不可能产生空间碎片。

不过,在统一尺寸的分配方式中,也还要注意如下两个问题:
1,不同大小的表最好设置不同大小的extent的表空间。对于几个GB的表,采用1MB的extent大小是比较合理的;如果表非常大,如 几十GB或几百GB,则可以考虑8MB、16MB、32MB甚至更大的extent尺寸。这种情况下,创建不同extent大小的表空间即可。
2,如果采用了比较大的extent大小,注意每个数据文件后面的空间浪费。如一个数据文件大小是2000MB,每个extent大小为64MB,但是,因为位图与数据文件头占了64KB,所以(2000M-64K)/64M是除不尽的,必将造成每个数据文件后面浪费差不多64MB的空间。这样的情况下,可以考虑把数据文件大小设置为2001Mb,就可以避免空间浪费了。



IOT
~~~~~~~~~~~~~
@connect /
drop table iot;
drop table heap;
set echo on 
set linesize 121
clear screen
create table iot
( username         varchar2(30),
  document_name    varchar2(30),
  other_data       char(1000),
  constraint iot_pk
  primary key (username,document_name)
)
organization index
/
create table heap
( username         varchar2(30),
  document_name    varchar2(30),
  other_data       char(1000),
  constraint heap_pk
  primary key (username,document_name)
)
/
pause


clear screen
begin
    for i in 1 .. 100
    loop
        for x in ( select username from all_users )
        loop
            insert into heap
            (username,document_name,other_data)
            values
            ( x.username, x.username || '_' || i, 'x' ); 
            insert into iot
            (username,document_name,other_data)
            values
            ( x.username, x.username || '_' || i, 'x' );
        end loop;
    end loop;
    commit;
end;
/
exec dbms_stats.gather_table_stats( user, 'IOT', cascade=>true );
exec dbms_stats.gather_table_stats( user, 'HEAP', cascade=>true );
pause

clear screen
column val format a25
select * from index_stats;
pause
select * 
  from table(cols_as_rows('select * from index_stats where rownum=1'))
 where rownum <= 10;
pause
column cname format a25
column t1 format a20
column t2 format a20
clear screen
set pause on
select a.cname, 
       decode( is_number(a.val),0,a.val,round(a.val,2)) t1, 
       decode( is_number(b.val),0,b.val,round(b.val,2)) t2,
	   case when is_number(a.val) = 1 and is_number(b.val) = 1
	        then to_char( decode(a.val,'0',null,round(b.val/a.val*100,2) ), '9,999.00' )
		 end pct
  from table( cols_as_rows( q'|select * 
                                 from index_stats 
                                where name = 'UNCOMPRESSED_IDX' |' ) ) a,
       table( cols_as_rows( q'|select * 
                                 from index_stats 
                                where name = 'COMPRESSED_IDX' |' ) ) b
     where a.cname = b.cname
/
set pause off

位图索引测试
~~~~~~~~~~~~~~~~~~~
connect /

set echo on
drop table emp;

clear screen
create table emp
as
select * 
  from scott.emp;

create bitmap index job_idx on emp(job);
pause

column bits format a30
clear screen
with jobs as (select distinct job from emp),
     emps as (select job, row_number() over (order by rowid) rn from emp),
     cnt  as (select count(*) cnt from emp)
select job, 
       ltrim(sys_connect_by_path( bit, '-' ),'-') bits
  from (
select jobs.job, 
       case when jobs.job = emps.job then '1' else '0' end bit, 
	   emps.rn
  from jobs, emps
       )
 where level = (select cnt from cnt)
 start with rn=1
 connect by prior job = job and prior rn = rn-1
/
pause

clear screen
select ename, job from emp where ename like 'S%';
update emp set job = 'CLERK' where ename = 'SCOTT';
declare
    pragma autonomous_transaction;
begin
    update emp set job = 'ANALYST' where ename = 'SMITH';
    commit;
end;
/
pause

clear screen
declare
    pragma autonomous_transaction;
begin
    insert into emp(empno,job) values (1234,'CLERK');
    commit;
end;
/
rollback;
pause

测试过程:
SQL> drop table emp;
drop table emp
           *
ERROR 位于第 1 行:
ORA-00942: 表或视图不存在


SQL> create table emp
  2  as
  3  select *
  4    from scott.emp;

表已创建。

SQL> create bitmap index job_idx on emp(job);

索引已创建。

SQL> column bits format a30
SQL> with jobs as (select distinct job from emp),
  2       emps as (select job, row_number() over (order by rowid) rn from emp),
  3       cnt  as (select count(*) cnt from emp)
  4  select job,
  5         ltrim(sys_connect_by_path( bit, '-' ),'-') bits
  6    from (
  7  select jobs.job,
  8         case when jobs.job = emps.job then '1' else '0' end bit,
  9        emps.rn
 10    from jobs, emps
 11         )
 12   where level = (select cnt from cnt)
 13   start with rn=1
 14   connect by prior job = job and prior rn = rn-1
 15  /

JOB       BITS
--------- ------------------------------
ANALYST   0-0-0-0-0-0-0-1-0-0-0-0-1-0
CLERK     1-0-0-0-0-0-0-0-0-0-1-1-0-1
MANAGER   0-0-0-1-0-1-1-0-0-0-0-0-0-0
PRESIDENT 0-0-0-0-0-0-0-0-1-0-0-0-0-0
SALESMAN  0-1-1-0-1-0-0-0-0-1-0-0-0-0

SQL> select ename, job from emp where ename like 'S%';

ENAME      JOB
---------- ---------
SMITH      CLERK
SCOTT      ANALYST

SQL> update emp set job = 'CLERK' where ename = 'SCOTT';

已更新 1 行。

SQL> declare
  2      pragma autonomous_transaction;
  3  begin
  4      update emp set job = 'ANALYST' where ename = 'SMITH';
  5      commit;
  6  end;
  7  /
declare
*
ERROR 位于第 1 行:
ORA-00060: 等待资源时检测到死锁
ORA-06512: 在line 4


SQL> declare
  2      pragma autonomous_transaction;
  3  begin
  4      insert into emp(empno,job) values (1234,'CLERK');
  5      commit;
  6  end;
  7  /
declare
*
ERROR 位于第 1 行:
ORA-00060: 等待资源时检测到死锁
ORA-06512: 在line 4

SQL> rollback;

回退已完成。

SQL>

  
cluster的测试  
~~~~~~~~~~~~~~~~~~~
connect /

set echo on

drop table emp;
drop table emp_heap;
drop table dept;
drop table dept_heap;
drop cluster emp_dept_cluster;


clear screen
create cluster emp_dept_cluster
( deptno number(5) )
size 1024
/
create index emp_dept_cluster_idx
on cluster emp_dept_cluster
/
pause


clear screen
create table dept
( deptno number(5) primary key,
  dname  varchar2(14),
  loc    varchar2(13)
)
cluster emp_dept_cluster(deptno)
/
create table dept_heap
( deptno number(5) primary key,
  dname  varchar2(14),
  loc    varchar2(13)
)
/
pause

clear screen
create table emp
( empno    number primary key,
  ename    varchar2(10), job      varchar2(9),
  mgr      number,       hiredate date,
  sal      number,       comm     number,
  deptno   number(5) references dept(deptno)
)
cluster emp_dept_cluster(deptno);
create table emp_heap
( empno    number primary key,
  ename    varchar2(10), job      varchar2(9),
  mgr      number,       hiredate date,
  sal      number,       comm     number,
  deptno   number(5) references dept_heap(deptno)
);
create index emp_heap_deptno_idx on emp_heap(deptno);
pause


clear screen
insert into dept (deptno, dname, loc )
select rownum, 
       substr( object_name, 1, dbms_random.value( 5, 14 ) ),
       substr( owner, 1, dbms_random.value( 8, 13 ) )
  from stage
 where rownum <= 10000
/
insert into dept_heap (deptno, dname, loc )
select rownum, 
       substr( object_name, 1, dbms_random.value( 5, 14 ) ),
       substr( owner, 1, dbms_random.value( 8, 13 ) )
  from stage
 where rownum <= 10000
/
pause

clear screen
insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno )
select object_id empno, 
       substr(object_name,1,10) ename, substr(object_name,1,9) job,
       object_id mgr, created hiredate, data_object_id sal,
       data_object_id comm,
       mod(rownum,10000)+1 deptno
  from stage
/
insert into emp_heap (empno, ename, job, mgr, hiredate, sal, comm, deptno )
select object_id empno, 
       substr(object_name,1,10) ename, substr(object_name,1,9) job,
       object_id mgr, created hiredate, data_object_id sal,
       data_object_id comm,
       mod(rownum,10000)+1 deptno
  from stage
/
pause

clear screen
exec dbms_stats.gather_table_stats( user, 'EMP' );
exec dbms_stats.gather_table_stats( user, 'EMP_HEAP' );
exec dbms_stats.gather_table_stats( user, 'DEPT' );
exec dbms_stats.gather_table_stats( user, 'DEPT_HEAP' );
exec dbms_stats.gather_index_stats( user, 'EMP_DEPT_CLUSTER_IDX' );
pause


column PLAN_TABLE_OUTPUT format a72 truncate
clear screen
delete from plan_table;
explain plan for
select *
  from emp, dept
 where emp.deptno = dept.deptno
   and dept.deptno = 10
/
pause
clear scree
select * from table(dbms_xplan.display);
pause

clear screen
delete from plan_table;
explain plan for
select *
  from emp_heap, dept_heap
 where emp_heap.deptno = dept_heap.deptno
   and dept_heap.deptno = 10
/
pause
clear scree
select * from table(dbms_xplan.display);
pause


set termout off
commit;
select emp.ename, dept.dname
  from emp, dept
 where emp.deptno = dept.deptno
   and dept.deptno = 10
/
select emp_heap.ename, dept_heap.dname
  from emp_heap, dept_heap
 where emp_heap.deptno = dept_heap.deptno
   and dept_heap.deptno = 10
/
commit;
set termout on

clear scree
alter system flush buffer_cache;
exec dbms_monitor.session_trace_enable( waits=>true );
select emp.ename, dept.dname
  from emp, dept
 where emp.deptno = dept.deptno
   and dept.deptno = 10
/
select emp_heap.ename, dept_heap.dname
  from emp_heap, dept_heap
 where emp_heap.deptno = dept_heap.deptno
   and dept_heap.deptno = 10
/
pause

clear screen
select dbms_rowid.rowid_block_number( emp.rowid ) erid, 
       dbms_rowid.rowid_block_number( dept.rowid ) drid
  from emp, dept
 where emp.deptno = dept.deptno
   and dept.deptno = 10
/
pause
clear screen
select dbms_rowid.rowid_block_number( emp_heap.rowid ) erid, 
       dbms_rowid.rowid_block_number( dept_heap.rowid ) drid
  from emp_heap, dept_heap
 where emp_heap.deptno = dept_heap.deptno
   and dept_heap.deptno = 10
/
pause

clear screen
select count(distinct rid) , count(*)
  from (select rowid rid from dept 
         union all 
        select rowid rid from emp)
/
select count(distinct rid) , count(*)
  from (select rowid rid from dept_heap 
         union all 
        select rowid rid from emp_heap)
/
pause

clear screen
drop table emp;
drop table dept;
drop table emp_heap;
drop table dept_heap;
drop cluster emp_dept_cluster;
clear screen
测试结果:
SQL> insert into dept (deptno, dname, loc )
  2  select rownum,
  3         substr( object_name, 1, dbms_random.value( 5, 14 ) ),
  4         substr( owner, 1, dbms_random.value( 8, 13 ) )
  5    from stage
  6   where rownum <= 10000
  7  /

已创建10000行。

SQL> insert into dept_heap (deptno, dname, loc )
  2  select rownum,
  3         substr( object_name, 1, dbms_random.value( 5, 14 ) ),
  4         substr( owner, 1, dbms_random.value( 8, 13 ) )
  5    from stage
  6   where rownum <= 10000
  7  /

已创建10000行。

SQL> insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno )
  2  select object_id empno,
  3         substr(object_name,1,10) ename, substr(object_name,1,9) job,
  4         object_id mgr, created hiredate, data_object_id sal,
  5         data_object_id comm,
  6         mod(rownum,10000)+1 deptno
  7    from stage
  8  /

已创建40707行。

SQL> insert into emp_heap (empno, ename, job, mgr, hiredate, sal, comm, deptno )
  2  select object_id empno,
  3         substr(object_name,1,10) ename, substr(object_name,1,9) job,
  4         object_id mgr, created hiredate, data_object_id sal,
  5         data_object_id comm,
  6         mod(rownum,10000)+1 deptno
  7    from stage
  8  /

已创建40707行。

SQL> exec dbms_stats.gather_table_stats( user, 'EMP' );

PL/SQL 过程已成功完成。

SQL> exec dbms_stats.gather_table_stats( user, 'EMP_HEAP' );

PL/SQL 过程已成功完成。

SQL> exec dbms_stats.gather_table_stats( user, 'DEPT' );

PL/SQL 过程已成功完成。

SQL> exec dbms_stats.gather_table_stats( user, 'DEPT_HEAP' );

PL/SQL 过程已成功完成。

SQL> exec dbms_stats.gather_index_stats( user, 'EMP_DEPT_CLUSTER_IDX' );

PL/SQL 过程已成功完成。

SQL> column PLAN_TABLE_OUTPUT format a72 truncate
SQL> delete from plan_table;

已删除0行。

SQL> explain plan for
  2  select *
  3    from emp, dept
  4   where emp.deptno = dept.deptno
  5     and dept.deptno = 10
  6  /

已解释。

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------
Plan hash value: 1728853682

------------------------------------------------------------------------
| Id  | Operation                    | Name                 | Rows  | By
------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                      |     4 |
|   1 |  NESTED LOOPS                |                      |     4 |
|   2 |   TABLE ACCESS BY INDEX ROWID| DEPT                 |     1 |
|*  3 |    INDEX UNIQUE SCAN         | SYS_C005422          |     1 |
|   4 |   TABLE ACCESS CLUSTER       | EMP                  |     4 |
|*  5 |    INDEX UNIQUE SCAN         | EMP_DEPT_CLUSTER_IDX |     1 |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------
------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("DEPT"."DEPTNO"=10)
   5 - access("EMP"."DEPTNO"=10)

已选择18行。

SQL> delete from plan_table;

已删除6行。

SQL> explain plan for
  2  select *
  3    from emp_heap, dept_heap
  4   where emp_heap.deptno = dept_heap.deptno
  5     and dept_heap.deptno = 10
  6  /

已解释。

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------
Plan hash value: 3849298615

------------------------------------------------------------------------
| Id  | Operation                    | Name                | Rows  | Byt
------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                     |     4 |   2
|   1 |  NESTED LOOPS                |                     |     4 |   2
|   2 |   TABLE ACCESS BY INDEX ROWID| DEPT_HEAP           |     1 |
|*  3 |    INDEX UNIQUE SCAN         | SYS_C005423         |     1 |
|   4 |   TABLE ACCESS BY INDEX ROWID| EMP_HEAP            |     4 |   1
|*  5 |    INDEX RANGE SCAN          | EMP_HEAP_DEPTNO_IDX |     4 |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------
------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("DEPT_HEAP"."DEPTNO"=10)
   5 - access("EMP_HEAP"."DEPTNO"=10)

已选择18行。

SQL> set linesize 120
SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------
Plan hash value: 3849298615

------------------------------------------------------------------------
| Id  | Operation                    | Name                | Rows  | Byt
------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                     |     4 |   2
|   1 |  NESTED LOOPS                |                     |     4 |   2
|   2 |   TABLE ACCESS BY INDEX ROWID| DEPT_HEAP           |     1 |
|*  3 |    INDEX UNIQUE SCAN         | SYS_C005423         |     1 |
|   4 |   TABLE ACCESS BY INDEX ROWID| EMP_HEAP            |     4 |   1
|*  5 |    INDEX RANGE SCAN          | EMP_HEAP_DEPTNO_IDX |     4 |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------
------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("DEPT_HEAP"."DEPTNO"=10)
   5 - access("EMP_HEAP"."DEPTNO"=10)

已选择18行。

SQL> set termout off
SQL> commit;

提交完成。

SQL> select emp.ename, dept.dname
  2    from emp, dept
  3   where emp.deptno = dept.deptno
  4     and dept.deptno = 10
  5  /

ENAME      DNAME
---------- --------------
MAP_OBJECT RE$NV_LIST
/c7d805c9_ RE$NV_LIST
/29bb36f7_ RE$NV_LIST
/ce66521c_ RE$NV_LIST
/7dc9ed4e_ RE$NV_LIST

SQL> select emp_heap.ename, dept_heap.dname
  2    from emp_heap, dept_heap
  3   where emp_heap.deptno = dept_heap.deptno
  4     and dept_heap.deptno = 10
  5  /

ENAME      DNAME
---------- --------------
MAP_OBJECT RE$NV_
/c7d805c9_ RE$NV_
/29bb36f7_ RE$NV_
/ce66521c_ RE$NV_
/7dc9ed4e_ RE$NV_

SQL> commit;

提交完成。

SQL> set termout on
SQL> alter system flush buffer_cache;
alter system flush buffer_cache
*
第 1 行出现错误:
ORA-01031: 权限不足


SQL> exec dbms_monitor.session_trace_enable( waits=>true );

PL/SQL 过程已成功完成。

SQL> select emp.ename, dept.dname
  2    from emp, dept
  3   where emp.deptno = dept.deptno
  4     and dept.deptno = 10
  5  /

ENAME      DNAME
---------- --------------
MAP_OBJECT RE$NV_LIST
/c7d805c9_ RE$NV_LIST
/29bb36f7_ RE$NV_LIST
/ce66521c_ RE$NV_LIST
/7dc9ed4e_ RE$NV_LIST

SQL> select emp_heap.ename, dept_heap.dname
  2    from emp_heap, dept_heap
  3   where emp_heap.deptno = dept_heap.deptno
  4     and dept_heap.deptno = 10
  5  /

ENAME      DNAME
---------- --------------
MAP_OBJECT RE$NV_
/c7d805c9_ RE$NV_
/29bb36f7_ RE$NV_
/ce66521c_ RE$NV_
/7dc9ed4e_ RE$NV_

SQL> select dbms_rowid.rowid_block_number( emp.rowid ) erid,
  2         dbms_rowid.rowid_block_number( dept.rowid ) drid
  3    from emp, dept
  4   where emp.deptno = dept.deptno
  5     and dept.deptno = 10
  6  /

      ERID       DRID
---------- ----------
      1536       1536
      1536       1536
      1536       1536
      1536       1536
      1536       1536

SQL> select dbms_rowid.rowid_block_number( emp_heap.rowid ) erid,
  2         dbms_rowid.rowid_block_number( dept_heap.rowid ) drid
  3    from emp_heap, dept_heap
  4   where emp_heap.deptno = dept_heap.deptno
  5     and dept_heap.deptno = 10
  6  /

      ERID       DRID
---------- ----------
      2175       2151
      3989       2151
      4138       2151
      4224       2151
      4379       2151

SQL> select count(distinct rid) , count(*)
  2    from (select rowid rid from dept
  3           union all
  4          select rowid rid from emp)
  5  /

COUNT(DISTINCTRID)   COUNT(*)
------------------ ----------
             40707      50707

SQL> select count(distinct rid) , count(*)
  2    from (select rowid rid from dept_heap
  3           union all
  4          select rowid rid from emp_heap)
  5  /

COUNT(DISTINCTRID)   COUNT(*)
------------------ ----------
             50707      50707

反转索引的测试
~~~~~~~~~~~~
connect /

create or replace type str2tblType as table of varchar2(30)
/

create or replace function str2tbl( p_str in varchar2, p_delim in varchar2 default ',' ) return str2tblType
PIPELINED
as
    l_str      long default p_str || p_delim;
    l_n        number;
begin
    loop
        l_n := instr( l_str, p_delim );
        exit when (nvl(l_n,0) = 0);
        pipe row( ltrim(rtrim(substr(l_str,1,l_n-1))) );
        l_str := substr( l_str, l_n+1 );
    end loop;
    return;
end;
/
set echo on
column dmp format a10
column rev format a10
set linesize 100

clear screen
set pause on
with data as
(select num, substr( dump(num,16), 14 ) dmp 
   from (select 90100+level num from dual connect by level <= 15))
select num, dmp, 
       (select max(decode(rownum,4,column_value)) || ',' ||
               max(decode(rownum,3,column_value)) || ',' ||
               max(decode(rownum,2,column_value)) || ',' ||
               max(decode(rownum,1,column_value)) 
	      from TABLE( str2tbl( dmp ) ) ) rev
  from data
/
pause
set pause off

测试结果:
SQL> create or replace type str2tblType as table of varchar2(30)
  2  /

类型已创建。

SQL> create or replace function str2tbl( p_str in varchar2, p_delim in varchar2 default ',' ) return str2tblType
  2  PIPELINED
  3  as
  4      l_str      long default p_str || p_delim;
  5      l_n        number;
  6  begin
  7      loop
  8          l_n := instr( l_str, p_delim );
  9          exit when (nvl(l_n,0) = 0);
 10          pipe row( ltrim(rtrim(substr(l_str,1,l_n-1))) );
 11          l_str := substr( l_str, l_n+1 );
 12      end loop;
 13      return;
 14  end;
 15  /

函数已创建。

SQL> set echo on
SQL> column dmp format a10
SQL> column rev format a10
SQL> with data as
  2  (select num, substr( dump(num,16), 14 ) dmp
  3     from (select 90100+level num from dual connect by level <= 15))
  4  select num, dmp,
  5         (select max(decode(rownum,4,column_value)) || ',' ||
  6                 max(decode(rownum,3,column_value)) || ',' ||
  7                 max(decode(rownum,2,column_value)) || ',' ||
  8                 max(decode(rownum,1,column_value))
  9           from TABLE( str2tbl( dmp ) ) ) rev
 10    from data
 11  /

       NUM DMP        REV
---------- ---------- ----------
     90101 c3,a,2,2   2,2,a,c3
     90102 c3,a,2,3   3,2,a,c3
     90103 c3,a,2,4   4,2,a,c3
     90104 c3,a,2,5   5,2,a,c3
     90105 c3,a,2,6   6,2,a,c3
     90106 c3,a,2,7   7,2,a,c3
     90107 c3,a,2,8   8,2,a,c3
     90108 c3,a,2,9   9,2,a,c3
     90109 c3,a,2,a   a,2,a,c3
     90110 c3,a,2,b   b,2,a,c3
     90111 c3,a,2,c   c,2,a,c3

       NUM DMP        REV
---------- ---------- ----------
     90112 c3,a,2,d   d,2,a,c3
     90113 c3,a,2,e   e,2,a,c3
     90114 c3,a,2,f   f,2,a,c3
     90115 c3,a,2,10  10,2,a,c3

已选择15行。

SQL>

域索引的测试
~~~~~~~~~~~~~~
drop table t;

create table t ( x varchar2(50) );

insert into t values ( '1 12345 987' );
insert into t values ( '1 12345 987 567' );
create index t_idx on t(x) indextype is ctxsys.context;

select x, score(0) 
  from t 
 where contains( x, '1 or 12345 or 567', 0 ) > 0
 order by 2 desc
/

10g下测试:9i下报错
SQL> create table t ( x varchar2(50) );

表已创建。

SQL>
SQL> insert into t values ( '1 12345 987' );

已创建 1 行。

SQL> insert into t values ( '1 12345 987 567' );

已创建 1 行。

SQL> create index t_idx on t(x) indextype is ctxsys.context;

索引已创建。

SQL> select x, score(0)
  2    from t
  3   where contains( x, '1 or 12345 or 567', 0 ) > 0
  4   order by 2 desc
  5  /

X                                                    SCORE(0)
-------------------------------------------------- ----------
1 12345 987 567                                             4
1 12345 987                                                 3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值