第十二章: 表(1)

  1、表的功能:存储、管理数据的基本单元(二维表:有行和列组成)
  2、表的类型:
      1)普通表:heap table :数据存储时,无序的,对它的访问采用全表扫描。
      2)分区表:(>2G)对大表进行优化   (Range Partitioning,List PartitioningHash Partitioning,Composite Partitioning)
---------按range 建立分区表
10:50:38 SQL> CREATE TABLE sales_range                                                                                                  
(salesman_id  NUMBER(5),
salesman_name VARCHAR2(30),
sales_amount  NUMBER(10),
sales_date    DATE)
PARTITION BY RANGE(sales_date)
10:51:11   7  (
10:51:11   8  lespace user01,
PARTITION sales_jan2000 VALUES LESS THAN(TO_DATE('04/01/2011','MM/DD/YYYY')) tablespace user01,
PARTITION sales_feb2000 VALUES LESS THAN(TO_DATE('07/01/2011','MM/DD/YYYY')) tablespace user02,
PARTITION sales_mar2000 VALUES LESS THAN(TO_DATE('10/01/2011','MM/DD/YYYY'))  tablespace user03,
PARTITION sales_apr2000 VALUES LESS THAN(TO_DATE('01/01/2012','MM/DD/YYYY'))  tablespace user04
10:51:11  12  );                                                                                                                        

Table created.

10:51:12 SQL>

10:55:19 SQL> insert into  sales_range  values ( 1001,'tom',1000,'2011-02-01');                                                         

1 row created.

10:55:34 SQL> insert into  sales_range  values ( 1002,'jerry',1000,'2011-05-01');                                                       

1 row created.

10:55:43 SQL> insert into  sales_range  values ( 1003,'rose',1000,'2011-08-01');                                                        

1 row created.

10:55:55 SQL> insert into  sales_range  values ( 1004,'john',1000,'2011-01-01');                                                        

1 row created.

10:56:04 SQL> select * from sales_range partition (sales_jan2000);                                                                      

SALESMAN_ID SALESMAN_NAME                  SALES_AMOUNT SALES_DATE
----------- ------------------------------ ------------ -------------------
       1001 tom                                    1000 2011-02-01 00:00:00
       1004 john                                   1000 2011-01-01 00:00:00

10:56:09 SQL> insert into  sales_range  values ( 1005,'john',1000,'2011-11-01');                                                        

1 row created.

10:56:34 SQL> select * from sales_range partition (sales_jan2000);                                                                      

SALESMAN_ID SALESMAN_NAME                  SALES_AMOUNT SALES_DATE
----------- ------------------------------ ------------ -------------------
       1001 tom                                    1000 2011-02-01 00:00:00
       1004 john                                   1000 2011-01-01 00:00:00

10:56:36 SQL> select * from sales_range partition (sales_feb2000);                                                                      

SALESMAN_ID SALESMAN_NAME                  SALES_AMOUNT SALES_DATE
----------- ------------------------------ ------------ -------------------
       1002 jerry                                  1000 2011-05-01 00:00:00

10:56:40 SQL> select * from sales_range partition (sales_mar2000);                                                                      

SALESMAN_ID SALESMAN_NAME                  SALES_AMOUNT SALES_DATE
----------- ------------------------------ ------------ -------------------
       1003 rose                                   1000 2011-08-01 00:00:00

10:56:47 SQL> select * from sales_range partition (sales_apr2000);                                                                      

SALESMAN_ID SALESMAN_NAME                  SALES_AMOUNT SALES_DATE
----------- ------------------------------ ------------ -------------------
       1005 john                                   1000 2011-11-01 00:00:00

10:56:52 SQL> select * from sales_range ;                                                                                               

SALESMAN_ID SALESMAN_NAME                  SALES_AMOUNT SALES_DATE
----------- ------------------------------ ------------ -------------------
       1001 tom                                    1000 2011-02-01 00:00:00
       1004 john                                   1000 2011-01-01 00:00:00
       1002 jerry                                  1000 2011-05-01 00:00:00
       1003 rose                                   1000 2011-08-01 00:00:00
       1005 john                                   1000 2011-11-01 00:00:00

10:57:08 SQL>

      3)索引组织表(IOT)(如果表经常以主键为索引查询,可建立索引组织表,加快表的访问速度)
     
 建立索引组织表
04:33:59 SQL> create table sales_info(
04:34:11   2  onstraid number(6)  primary key,
04:34:55   3  customer_name varchar2(30) ,slaes_amount number(10,2),
04:35:26   4  sales_date date,remark varchar2(2000)
04:35:56   5  ) organization index tablespace users01
04:36:28   6  pctthreshold 20 including remark
04:36:46   7  overflow tablespace users02;

Table created.
定义索引表时,主键约束和ORGANIZATION  index 选项必须指定。
PCTTHRESHOLD :用于指定数据块中为键列和部分非键列数据所预留空间的百分比;如果数据块剩余空间低于PCTTHRESHOLD 设置,Oracle会将其他数据存放到溢出段。
INCLUDING column :用于指定数据被存放到溢出段的起始列。
OVERFLOW TABLESPACE:用于指定溢出段所在的表空间。


      4)簇:cluster (多表链接查询)
      1)建立簇
09:31:25 SQL> create cluster dept_emp_clu (deptno number(3))
09:33:19   2  pctfree 20 pctused 60
09:33:31   3  size 500 tablespace users01;

Cluster created.
2)建立簇表
09:33:56 SQL> create table department(
09:34:21   2  id number(3) primary key,
09:34:40   3  dname varchar(2) ,loc varchar2(13))
09:35:07   4  cluster dept_emp_clu(id);

Table created.

09:35:24 SQL> create table employee(
09:36:00   2  eno number(4) primary key ,
09:36:21   3  ename varchar2(10),
09:36:34   4  job varchar2(9),
09:36:50   5  mgr number(4),
09:36:59   6  hiredate date,
09:37:05   7  sal number(7,2),
09:37:14   8  comm number(7,2),
09:37:26   9  dept_id number(3) references department
09:38:09  10  ) cluster dept_emp_clu(dept_id);

Table created.
3)建立索引
09:38:31 SQL> create index dept_emp_idx on cluster dept_emp_clu
09:39:12   2   tablespace users02;

Index created.


----------------cluster访问和普通表连接查询访问 对比
22:27:03 SQL> select e.eno,e.ename,e.sal,d.id,d.dname,d.loc from employee e,department d                                                
22:27:08   2   where e.dept_id=d.id;                                                                                                    

       ENO ENAME             SAL         ID DNAME                LOC
---------- ---------- ---------- ---------- -------------------- -------------
      7782 CLARK            2450         10 ACCOUNTING           NEW YORK
      7839 KING             5000         10 ACCOUNTING           NEW YORK
      7934 MILLER           1300         10 ACCOUNTING           NEW YORK
      7369 SMITH             800         20 RESEARCH             DALLAS
      7566 JONES            2975         20 RESEARCH             DALLAS
      7788 SCOTT            3000         20 RESEARCH             DALLAS
      7876 ADAMS            1100         20 RESEARCH             DALLAS
      7902 FORD             3000         20 RESEARCH             DALLAS
      7499 ALLEN            1600         30 SALES                CHICAGO
      7521 WARD             1250         30 SALES                CHICAGO
      7654 MARTIN           1250         30 SALES                CHICAGO
      7698 BLAKE            2850         30 SALES                CHICAGO
      7844 TURNER           1500         30 SALES                CHICAGO
      7900 JAMES             950         30 SALES                CHICAGO

14 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1419571889

--------------------------------------------
| Id  | Operation             | Name       |
--------------------------------------------
|   0 | SELECT STATEMENT      |            |
|   1 |  NESTED LOOPS         |            |
|   2 |   TABLE ACCESS FULL   | DEPARTMENT |
|   3 |   TABLE ACCESS CLUSTER| EMPLOYEE   |
--------------------------------------------

Note
-----
   - rule based optimizer used (consider using cbo)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         17  consistent gets
          0  physical reads
          0  redo size
       1042  bytes sent via SQL*Net to client
        384  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         14  rows processed

22:27:09 SQL> select e.empno,e.ename,e.sal,d.dname,d.dname,d.loc from emp e,dept d                                                      
22:27:35   2  where e.deptno=d.deptno;                                                                                                  

     EMPNO ENAME             SAL DNAME          DNAME          LOC
---------- ---------- ---------- -------------- -------------- -------------
      7369 SMITH             800 RESEARCH       RESEARCH       DALLAS
      7499 ALLEN            1600 SALES          SALES          CHICAGO
      7521 WARD             1250 SALES          SALES          CHICAGO
      7566 JONES            2975 RESEARCH       RESEARCH       DALLAS
      7654 MARTIN           1250 SALES          SALES          CHICAGO
      7698 BLAKE            2850 SALES          SALES          CHICAGO
      7782 CLARK            2450 ACCOUNTING     ACCOUNTING     NEW YORK
      7788 SCOTT            3000 RESEARCH       RESEARCH       DALLAS
      7839 KING             5000 ACCOUNTING     ACCOUNTING     NEW YORK
      7844 TURNER           1500 SALES          SALES          CHICAGO
      7876 ADAMS            1100 RESEARCH       RESEARCH       DALLAS
      7900 JAMES             950 SALES          SALES          CHICAGO
      7902 FORD             3000 RESEARCH       RESEARCH       DALLAS
      7934 MILLER           1300 ACCOUNTING     ACCOUNTING     NEW YORK

14 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 351108634

----------------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |         |    14 |   518 |     4   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                |         |    14 |   518 |     4   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL          | EMP     |    14 |   238 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     1 |    20 |     1   (0)| 00:00:01 |
|*  4 |    INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00:00:01 |
----------------------------------------------------------------------------------------

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

   4 - access("E"."DEPTNO"="D"."DEPTNO")


Statistics
----------------------------------------------------------
        139  recursive calls
          0  db block gets
         59  consistent gets
          3  physical reads
          0  redo size
       1257  bytes sent via SQL*Net to client
        384  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          7  sorts (memory)
          0  sorts (disk)
         14  rows processed

22:27:43 SQL>

3、 rowid :行号(伪列)精确的定义记录的物理位置

        extended rowid: object id (6),relative file id(3),block id (6),row id(3)
       
    分析rowid
 ---------普通表和簇表的rowid ,对比
   
    22:31:27 SQL> select rowid ,ename,sal from emp;                                                                                         

ROWID              ENAME             SAL
------------------ ---------- ----------
AAACYCAAEAAAAAfAAA SMITH             800
AAACYCAAEAAAAAfAAB ALLEN            1600
AAACYCAAEAAAAAfAAC WARD             1250
AAACYCAAEAAAAAfAAD JONES            2975
AAACYCAAEAAAAAfAAE MARTIN           1250
AAACYCAAEAAAAAfAAF BLAKE            2850
AAACYCAAEAAAAAfAAG CLARK            2450
AAACYCAAEAAAAAfAAH SCOTT            3000
AAACYCAAEAAAAAfAAI KING             5000
AAACYCAAEAAAAAfAAJ TURNER           1500
AAACYCAAEAAAAAfAAK ADAMS            1100
AAACYCAAEAAAAAfAAL JAMES             950
AAACYCAAEAAAAAfAAM FORD             3000
AAACYCAAEAAAAAfAAN MILLER           1300

14 rows selected.

22:31:31 SQL> select rowid,deptno,dname from dept;                                                                                      

ROWID                  DEPTNO DNAME
------------------ ---------- --------------
AAACYAAAEAAAAAPAAA         10 ACCOUNTING
AAACYAAAEAAAAAPAAB         20 RESEARCH
AAACYAAAEAAAAAPAAC         30 SALES
AAACYAAAEAAAAAPAAD         40 OPERATIONS

22:31:42 SQL> select rowid,id,dname from department;                                                                                    

ROWID                      ID DNAME
------------------ ---------- --------------------
AAACZNAAEAAAABWAAA         10 ACCOUNTING
AAACZNAAEAAAABWAAB         20 RESEARCH
AAACZNAAEAAAABWAAC         30 SALES
AAACZNAAEAAAABWAAD         40 OPERATIONS

22:31:58 SQL> select rowid ,eno,ename,sal from employee;                                                                                

ROWID                     ENO ENAME             SAL
------------------ ---------- ---------- ----------
AAACZNAAEAAAABWAAA       7369 SMITH             800
AAACZNAAEAAAABWAAB       7499 ALLEN            1600
AAACZNAAEAAAABWAAC       7521 WARD             1250
AAACZNAAEAAAABWAAD       7566 JONES            2975
AAACZNAAEAAAABWAAE       7654 MARTIN           1250
AAACZNAAEAAAABWAAF       7698 BLAKE            2850
AAACZNAAEAAAABWAAG       7782 CLARK            2450
AAACZNAAEAAAABWAAH       7788 SCOTT            3000
AAACZNAAEAAAABWAAI       7839 KING             5000
AAACZNAAEAAAABWAAJ       7844 TURNER           1500
AAACZNAAEAAAABWAAK       7876 ADAMS            1100
AAACZNAAEAAAABWAAL       7900 JAMES             950
AAACZNAAEAAAABWAAM       7902 FORD             3000
AAACZNAAEAAAABWAAN       7934 MILLER           1300

14 rows selected.

DECLARE  v_rowid_type  NUMBER;
    v_OBJECT_NUMBER  NUMBER;
    v_RELATIVE_FNO   NUMBER;
    v_BLOCK_NUMBERE_FNO   NUMBER;
    v_ROW_NUMBER   NUMBER;
    BEGIN
    DBMS_ROWID.rowid_info(rowid_in=>'&num',
    rowid_type  =>v_rowid_type,
    object_number  =>v_OBJECT_NUMBER,
   relative_fno  =>v_RELATIVE_FNO,
   block_number  =>v_BLOCK_NUMBERE_FNO,
   ROW_NUMBER =>v_ROW_NUMBER);
   DBMS_OUTPUT.put_line('ROWID_TYPE:' ||TO_CHAR(v_rowid_type));
   DBMS_OUTPUT.put_line('OBJECT_NUMBER:' ||TO_CHAR(v_OBJECT_NUMBER));
   DBMS_OUTPUT.put_line('RELATIVE_FNO:' ||TO_CHAR(v_RELATIVE_FNO));
   DBMS_OUTPUT.put_line('BLOCK_NUMBER:' ||TO_CHAR(v_BLOCK_NUMBERE_FNO));
   DBMS_OUTPUT.put_line('ROW_NUMBER:' ||TO_CHAR(v_ROW_NUMBER));
  END;
 /                                                                                                                                      

Enter value for num: old   7:     DBMS_ROWID.rowid_info(rowid_in=>'&num',
new   7:     DBMS_ROWID.rowid_info(rowid_in=>'',

PL/SQL procedure successfully completed.

22:36:48 SQL>                   set serverout on                                                                                        
22:36:53 SQL> /                                                                                                                         
Enter value for num: AAACZNAAEAAAABWAAA                                                                                                 
old   7:     DBMS_ROWID.rowid_info(rowid_in=>'&num',
new   7:     DBMS_ROWID.rowid_info(rowid_in=>'AAACZNAAEAAAABWAAA',
ROWID_TYPE:1
OBJECT_NUMBER:9805
RELATIVE_FNO:4
BLOCK_NUMBER:86
ROW_NUMBER:0

PL/SQL procedure successfully completed


DECLARE  v_rowid_type  NUMBER;
    v_OBJECT_NUMBER  NUMBER;
    v_RELATIVE_FNO   NUMBER;
    v_BLOCK_NUMBERE_FNO   NUMBER;
                                                                                                                                            DBMS_OUTPUT.put_line('BLOCK_NUMBER:' ||TO_CHAR(v_BLOCK_NUMBERE_FNO));
    v_ROW_NUMBER   NUMBER;
    BEGIN
    DBMS_ROWID.rowid_info(rowid_in=>'&num',
    rowid_type  =>v_rowid_type,
    object_number  =>v_OBJECT_NUMBER,
   relative_fno  =>v_RELATIVE_FNO,
   block_number  =>v_BLOCK_NUMBERE_FNO,
   ROW_NUMBER =>v_ROW_NUMBER);
   DBMS_OUTPUT.put_line('ROWID_TYPE:' ||TO_CHAR(v_rowid_type));
   DBMS_OUTPUT.put_line('OBJECT_NUMBER:' ||TO_CHAR(v_OBJECT_NUMBER));
   DBMS_OUTPUT.put_line('RELATIVE_FNO:' ||TO_CHAR(v_RELATIVE_FNO));
   DBMS_OUTPUT.put_line('BLOCK_NUMBER:' ||TO_CHAR(v_BLOCK_NUMBERE_FNO));
   DBMS_OUTPUT.put_line('ROW_NUMBER:' ||TO_CHAR(v_ROW_NUMBER));
  END;
22:38:10  19   /                                                                                                                        
Enter value for num: AAACZNAAEAAAABWAAM                                                                                                 
old   7:     DBMS_ROWID.rowid_info(rowid_in=>'&num',
new   7:     DBMS_ROWID.rowid_info(rowid_in=>'AAACZNAAEAAAABWAAM',
ROWID_TYPE:1
OBJECT_NUMBER:9805
RELATIVE_FNO:4
BLOCK_NUMBER:86
ROW_NUMBER:12

PL/SQL procedure successfully completed.


-------------在建立cluster的表,通过rowid,可以看到不同的表的记录放在了相同的block 上
22:32:12 SQL>
   
    11:29:43 SQL>                                                                                                                      
  1  DECLARE  v_rowid_type  NUMBER;
  2  v_OBJECT_NUMBER  NUMBER;
  3  v_RELATIVE_FNO   NUMBER;
  4  v_BLOCK_NUMBERE_FNO   NUMBER;
  5  v_ROW_NUMBER   NUMBER;
  6  BEGIN
  7  DBMS_ROWID.rowid_info(rowid_in=>'&num',
  8  rowid_type  =>v_rowid_type,
  9  object_number  =>v_OBJECT_NUMBER,
 10  relative_fno  =>v_RELATIVE_FNO,
 11  block_number  =>v_BLOCK_NUMBERE_FNO,
 12  ROW_NUMBER =>v_ROW_NUMBER);
 13  DBMS_OUTPUT.put_line('ROWID_TYPE:' ||TO_CHAR(v_rowid_type));
 14  DBMS_OUTPUT.put_line('OBJECT_NUMBER:' ||TO_CHAR(v_OBJECT_NUMBER));
 15  DBMS_OUTPUT.put_line('RELATIVE_FNO:' ||TO_CHAR(v_RELATIVE_FNO));
 16  DBMS_OUTPUT.put_line('BLOCK_NUMBER:' ||TO_CHAR(v_BLOCK_NUMBERE_FNO));
 17  DBMS_OUTPUT.put_line('ROW_NUMBER:' ||TO_CHAR(v_ROW_NUMBER));
 18* END;
 /                                                                                                                         
Enter value for num: AAAMfMAAEAAAAAgAAB                                                                                                 
old   7: DBMS_ROWID.rowid_info(rowid_in=>'&num',
new   7: DBMS_ROWID.rowid_info(rowid_in=>'AAAMfMAAEAAAAAgAAB',
ROWID_TYPE:1
OBJECT_NUMBER:51148
RELATIVE_FNO:4
BLOCK_NUMBER:32
ROW_NUMBER:1

PL/SQL procedure successfully completed.
11:31:54 SQL>                                                                                                                       
  1  select object_name,object_id,object_type ,status from user_objects
  2*   where object_name='EMP'

OBJECT_NAME                     OBJECT_ID OBJECT_TYPE         STATUS
------------------------------ ---------- ------------------- ----------
EMP                                 51148 TABLE               VALID

11:32:56 SQL> COL SEGMENT_NAME FOR A30                                                                                                  
11:33:02 SQL>                                                                                                                       
  1  select segment_name,tablespace_name,file_id,block_id from dba_extents
  2*   where segment_name='EMP'

SEGMENT_NAME                   TABLESPACE_NAME                   FILE_ID   BLOCK_ID
------------------------------ ------------------------------ ---------- ----------
EMP                            USERS                                   4         25

11:33:02 SQL>

11:33:55 SQL> select segment_name,tablespace_name,file_id,block_id,EXTENT_ID,BYTES/1024 from dba_extents                                
11:34:25   2    where segment_name='EMP';                                                                                               

SEGMENT_NAME                   TABLESPACE_NAME                   FILE_ID   BLOCK_ID  EXTENT_ID BYTES/1024
------------------------------ ------------------------------ ---------- ---------- ---------- ----------
EMP                            USERS                                   4         25          0         64

11:34:27 SQL>