第十二章: 表(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>