普通表
分区表 : 如果一个表太大了,那么就会在这个大表的基础上,在分为子表,叫做 partition. 每个 row 是存储在一起的,比如 有1000行数据,可能 前 500 rows 存储在一个 partition 里边,后 500 rows 存储在一个 partition里。每个分区是一个 segment, 并且可以存储在不同的tablespace中。
Index-organized tables : 这个“索引表” 不同于以往意义的索引,它是将存储的数据本身按照某种顺序进行了存储,所以查询效率很高。with a primary key index on one or more of its columns. an index-organized table maintains a single B- tree containing the primary key of the table and other column values.
集群 : Clustered tables , 很多表是有相关性的,比如 Join 多个表,那么,可以将多个表存储为集群,这样在查询时会提高效率。
Clusters have a cluster key, which is used to identify the rows that need to be stored together.
cluster key can consist of one or more columns.
Tables in a cluster have columns that correspond to the cluster key.
The cluster key is independent of the primary key.
99% 用的是 built-in 类型, 99% 使用 Scalar
数字型,文本型,日期型,二进制( LOB )
尽量用 varchar2 , 不要使用 char, 除非是固定格式,比如性别,只有 男,女
如果 oracle 内部表的列数超过 254列,oracle 会将一行 分成几块来存储。会加重 I/O 负荷。
索引是依附于表的。
对于任何一张表都有 ROWID,隐含的。
select ROWID, ID, NAME from employee;
ROWID 的内容, 可以看到 ROWID 可以快速定位一条记录的位置。
90% 一行放在一个 database block 中。( 一个 database block 中还可以放行 )
列存储的顺序通常就是你定义的列的顺序,并且如果某列的值是 NULL, 那么是不会存储该列的。
Row data is stored in database blocks as variable-length records. columns for a row are generally stored in the order in which they are defined and any trailing NULL are not stored. Note: A single byte for column length is required for non trailing NULL columns.
Each row in a table may have a different number of columns. Each row in a table has :
row header : 这行有多少列,还有链接信息,还有锁的情况。row lock
row data : 存储列的长度,还有列的值。列的值是紧挨着列的长度信息。 for each column, the oracle server stores the column length and value ( one byte is needed to store the column length if the column cannot exceed 250 bytes. A column that can be longer needs three length bytes. The column value is stored immediately following the column length bytes.)
该命令比较复杂。类似准备创建数据库一样,有个样本比较好。
创建 table 中的存储信息段
The STORAGE clause specifies storage characteristics for the table. 其中 :
Storage 信息
-- our db create table storage STORAGE ( INITIAL 64K MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT )
个人感觉创建 table 的时候, 不用特意指定storage, 因为在 tablespace 中已经指定了, 只要将他放在对应的tablespace中就可以了
我的感觉是对的.
The STORAGE clause specifies storage characteristics for the table. The storage allocated for the first extent is 200K. When a second extent is required it will be created at 200K also defined by the NEXT value. When a third extent is required, it will be created at 200K because the PCTINCREASE has been set to 0. The maximum amount of extents that can be used is set at 5. with the minimum set to 1.
PCTFREE 这个参数比较重要 ( 预留的空间,为了将来如果发生 update 等事务时,这个 block 还有空间可以使用, 如果这个值 ( 百分比)分配太小,那么当 update时,如果空间不够,就会发生将整个 block 搬家的事件,如果分配的空间太大,那么又是一种浪费 )
推荐 自动管理。
INITRANS : 控制同时能够操作 那个块的 transaction. Specifies the initial number of transaction entries allowcated within each data block allocated to the table. 范围 1 ~ 255 , 默认是 1. INITRANS ensures that a minimum number of concurrent transaction can update the block. In general , this value should not be changed from its default.
创建表的原则:
总的原则:减少资源竞争
创建临时表 temporary tables
Temporary tables can be created to hold session-private data that exists only for the duration of a transaction or session.
查询结果太大时,临时将结果缓存在磁盘上。
CREATE GLOBAL TEMPORARY TABLE
临时表的数据,只在一个事物或 session 中有效。
对数据不需要做 DML 加锁
也可以创建 索引,视图,触发器。
只有当前的 session 可以看到相应信息,visable, 即便是两个 session 使用的同一个临时表,互相也看不到。
一个用户不可能阻止别的用户访问临时表。即使 lock 临时表也无法阻止别的用户使用该表。
临时表也会产生 undo 和 redo 信息,但是很少。基本可以忽略。
用户的临时表是放在 自己临时表空间中,A 和 B 都用一个临时表,但是这个临时表存储在 2 个临时表空间中。
临时表只是定义了一个表的摸板,但是这个表并不存在,并没有产生真正的表空间。(没有分配磁盘), 这是与实际表的区别。
只是在运行时刻,才临时分配了一个 segment.
即 user1 用的时候,这个临时表,分配了一个空间, temp1
当 user2 用的时候,这个临时表,又分配了 temp2, 所以,虽然是一个gloable temporary table, 但其实是2张表。
on commit delete rows to specify that rows are only visible within the transaction
on commit preserve rows to specify that rows are visibile for the entire session
session 有效 : 例子
create global temporary table tmp_session on commit preserve rows
as select * from t where 1=0 ;
transaction 有效 : 例子
create global temporary table tmp_session on commit delete rows
as select * from t where 1=0 ;
提交事物后,session 级别的还会有数据存在,而 事物级别的数据就不存在了。
当该用户退出后,session 断了,那么 session 级别的数据也就没有了。
分析表 可以 得到 row size, 在性能调优提到。
Migration 移动 , 带来的后果就是 oracle 的性能下降。 I/O 要翻一翻。
应该尽量避免 Migration
Row chaining
如果一个条记录中有太多列,或者列太长,oracle 就会把它分成不同的部分,每个部分是 row piece, 每块里都包含指针,然后连接成一个完整记录。
也同样加重了 oracle 读取的负担。
检测的 Migration, Row chaining , oracle 中有个包,可以提供分析的功能。dbms_metadata 包
修改的内容,只能作用于新的 block.
限制 : The value of INITIAL cannot be modified for a table.
The value of NEXT specified will be rounded to a value that is multiple of the block size greater than or equal to the value specified.
以下情况,需要使用手工分配 额外空间。
可能需要对表的重新组织,类似磁盘碎片整理。
将数据 移动到另外的 segment中,保存 index, constraints, privilege 等信息。
Is being used to move a table to a different tablespace or reorganize extents
After moving a table you will have to rebuild the indexes to avoid some error.
前一章 有介绍过 高水位的问题,这点与 delete from table; 不一样。DDL
不常使用,8i版本都没有这个命令
Dropping a column can be time consuming and require a large amount of undo space. While dropping columns from large tables, checkpoints can be specified to minimize the use of undo space.
可以设置 column 为 unused
ALTER TABLE hr.employees SET UNUSED COLUMN 列名 CASCADE CONSTRAINTS
ALTER TABLE hr.employees DROP UNUSED COLUMNS CHECKPOINT 1000;
当你要删除 2 列时,如果是直接删除,那么所有的行都会被折腾 2 次,而如果先设置成 UNUSED, 设置完 这两列之后,再删除这两列,那么所有的行就只会被折腾 1 次。因为 drop 是 drop unused column , 所以,一次性将所有的 unused 全部删除。
DBA_TABLES
DBA_OBJECTS
ALTER TABLE table_name
RENAME COLUMN old_name TO new_name;
尽量不改,改名字很麻烦( 不改, 就当做不知道这个命令好了)