数据以堆的形式管理,增长数据时会使用段中找到的第一个能放下数据的自由空间,咱们见到的绝大部分的表都是堆表。堆表是数据库的默认表类型。sql
最简单的状况是数据库
create table test (c1 varchar2(10),c2 varchar2(24),c3 number(9,3)) ;
而后使用tom kyte的方法,尽量简单的建立表,调用dbms_metadata.get_ddl函数,查看详细定义,而后再根据这个详细版本,定制本身想要的版本。缓存
set long 5000 select dbms_metadata.get_ddl('TABLE','TEST') from dual; CREATE TABLE "SCOTT"."TEST" ( "C1" VARCHAR2(10), "C2" VARCHAR2(24), "C3" NUMBER(9,3) ) SEGMENT CREATION DEFERRED PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING TABLESPACE "USERS"
11g之后的版本,段会延迟到插入数据才建立,若是想当即建立段使用segment creation immediate,默认为defereed
可使用数据字典表dba_segments或者all_segments确认markdown
create table test (c1 varchar2(10),c2 varchar2(24),c3 number(9,3)) segment creation immediate ;
若是不指定表空间,则使用表所在用户的默认表空间。
指定表存储在users表空间里:oracle
create table test (c1 varchar2(10),c2 varchar2(24),c3 number(9,3)) tablespace users;
PCTUSED若是使用ASSM(自动段空间管理)的话,会被忽略,绝大部分状况是这样的,oracle也推荐这样。
PCTFREE用于在数据库块里预留空间用于更新,单到达设置比例后不会有新行插入该块,以避免产生行迁移.app
create table test (c1 varchar2(10),c2 varchar2(24),c3 number(9,3)) pctfree 20;
initrans控制数据库块头为事务预留的事务插槽个数,若是对该表进行插入和更新的事务很是多,建议将该值设置的稍微大一点。less
create table test (c1 varchar2(10),c2 varchar2(24),c3 number(9,3)) initrans 10;
使用什么缓存池来缓存该表的块
通常使用默认设置便可, 即default
对于访问很是频繁的表可使用 keep池,(通常在其余优化手段测试后才使用这种方法),须首先设置db_keep_cache_size参数。函数
create table test (c1 varchar2(10),c2 varchar2(24),c3 number(9,3)) storage (buffer_pool keep);
不管设置成那个在普通DML语句时都要产生日志文件,只有直接路径DML才有区别。绝大部分状况使用logging(默认)。只有在大量加载数据的状况下使用nologging来加快数据的加载性能
create table test (c1 varchar2(10),c2 varchar2(24),c3 number(9,3)) nologging storage (buffer_pool keep);
在直接路径加载或者传统路径加载启用或者禁用压缩。有nocompress(禁用压缩),
compress对直接路径插入有效
compress for oltp对直接路径和通常路径插入都有效测试
压缩的效果通常都比较好,若是cpu资源容许的状况下,可使用压缩提升对数据库缓冲区缓存的使用效率,能够放更加多的数据了,对于全表扫描较多的应用程序来讲是一个很好的优化。可是相应的会增长cpu的使用,使用前应该进行相应的测试。测试会不会对数据插入,修改形成影响。很是适合一次写入屡次修改类型数据。
使用 select blocks,avg_row_length,num_rows,compression,compress_for from user_tables where table_name='xxxxx'
检查压缩前和压缩后效果差别
能够在表建立时使用约束或者在表建立后增长、修改或者删除约束
约束分为行内约束和行外约束,行内约束指的是在定义列时候一块儿定义该列相关的约束。行外约束指的是单独一行定义约束。
create table test ( c1 varchar2(10) primary key, c2 varchar2(24) not null, c3 number(9,3) constraint c3_check check(c3>100), constarint c2_check check (c2 in ('China', 'Japan','USA')) ) ;
其中primary key 、not null、 c3_check为行内约束,c2_check为行外约束
enable 表示启用
disable 表示不启用
validate 表示当前表中全部数据都被验证了
novalidate 表示当前表中的数据没有被验证。
通常状况只需设置enable validate(默认)
其它组合用于对大数据进行ETL时使用节省时间
还有一个表示约束是延迟起效仍是当即起效。延迟起效表示在commit完成时进行检查约束是否正确,当即起效表示对该语句处理时进行判断是否知足约束
默认状况是当即起效
延迟起效的语法为
deferred initially immediate|deferred 只有这样设置了的约束才能在事务控制时使用约束控制延迟。
表示该列可不能够为空
表示该列的值在表内必须惟一,可是能够为null
create table test ( c1 varchar2(10), c2 varchar2(24), c3 number(9,3), constraint pk_test primary key (c1,c2), constraint uk_test unique (c3) ) ;
这些键表示的值在全表惟一且不为空(主键的全部列都不能为null),能够由单列做为主键或者多列组合做为主键
create table test ( c1 varchar2(10), c2 varchar2(24), c3 number(9,3), constraint pk_test primary key (c1,c2) ) ;
用于表示父子表,使用引用约束的表为子表,被引用约束的表为父表
create table parent ( c1 varchar2(10), c2 varchar2(24), c3 number(9,3), constraint pk_test primary key (c1,c2) ) ; create table child ( c1 varchar2(10), c2 varchar2(24), c3 number(9,3), c4 number(9,3), constraint fk_child foreign key (c1,c2) references parent(c1,c2) ) ; //父表删除一行,子表和其关联的行被删除 create table child1 ( c1 varchar2(10), c2 varchar2(24), c3 number(9,3), c4 number(9,3), constraint fk_child foreign key (c1,c2) references parent(c1,c2) on delete cascade ) ; //父表删除一行,子表和其关联的行被删除 create table child2 ( c1 varchar2(10), c2 varchar2(24), c3 number(9,3), c4 number(9,3), constraint fk_child foreign key (c1,c2) references parent(c1,c2) on delete set null ) ;
引用约束还有一个和性能关系很大的条件,若是不对子表的引用列加上索引,当父表更新或者删除时会锁定整个子表。
用于检查某些条件,大于,小于,在一个集合里面等等
create table test (c1 varchar2(10) primary key, c2 varchar2(24), c3 number(9,3), constraint c2_c3_check check(c2 in ('China','USA') and c3>5.0) enable validate) tablespace users pctfree 20 storage (buffer_pool keep);
索引组织表是将数据存储在索引结构里。索引组织表中的数据按照主键存储和排序。索引组织表首先是对于信息的获取很是有利。其次因为是按索引进行存储的,索引的前缀部分相同的键会存储在一块儿。IOT表对于信息获取,空间应用和OLAP至关有用。
IOT表有三个属性很重要
compress N表示对索引的前N项提取公因子。在重复度很高的状况下压缩性很是好。
能够对IOT表的主键使用
analyze index iot_pk validate structure;
而后查看index_stats表的opt_cmpr_count获取最优N值。
表示行数据量超过块大小的这个百分比时,剩余的列放到overflow里去。
行中从第一列到该列为止都存储在叶子块里,剩余的列放到overflow里。
容许你建立另外一个段,当数据行太长时溢出到这个段上来,以使IOT的叶子块尽可能容纳更多的行。
分区键必须是主键的子集
create table line (point_id varchar2(20), line_id varchar2(20), x number(10,3), y number(10,3), loc varchar2(20), time date, constraint pk_line primary key(line_id,point_id,time) ) organization index partition by range(time) (partition p0 values less than (to_date('2016-1-1','yyyy-mm-dd')) );
使用including控制overflow
create table address ( type varchar2(10), location varchar2(200), phone varchar2(20), detail varchar2(800), constraint pk_address primary key (type,location) ) organization index including location overflow; 使用pctthreshold控制overflow create table address ( type varchar2(10), location varchar2(200), phone varchar2(20), detail varchar2(800), constraint pk_address primary key (type,location) ) organization index pctthreshold 5 overflow; 使用including和pctthreshold的组合也是能够的,可是通常不是特别有用
分区是将一个表或者索引分红多个更小,更可管理的部分。逻辑上将只有一个表或索引,对外部使用该表的人而言,就是一个表和普通表没有任何分别,可是在物理上这一个表能够由多个分区组成,每一个分区都是一个独立的对象,能够单独处理,或是做为一个更大的部分被处理。
指定存储在一块儿的数据的区间,好比2016-3-1到2016-4-1的放在分区1,2016-4-1到2016-5-1的放在分区2,等等
常见使用方法有两种,常规区间分区和间隔分区
可是不论是哪一种分区方式,和普通表同样,能够在表后面指定PCTFREE、INITRANS、存储性质(基本上就是buffer_pool)、表空间等物理属性。若是分区没有覆写这些属性,则分区和表的这些性质保持一致
固然,每一个分区后均可以指定PCTFREE、INITRANS、存储性质(基本上就是buffer_pool)、表空间等物理属性
语法结构为
partition by range (column_name) (partition name1 values less than (value1), partition name2 values less than (valuee2), .... partition last_part values less than (maxvalue));
最后一个小于maxvalue是为了让全部状况均可以被表所包含。这里的小于,指的是严格小于,等于不包含在内。
举个例子
create table log ( text varchar2(255), rksj date ) pctfree 20 storage(buffer_pool default) partition by range(rksj) ( partition part_2016_3 values less than (to_date('2016-3-1','yyyy-mm-dd')), partition part_2016_4 values less than (to_date('2016-4-1','yyyy-mm-dd')) pctfree 10 storage(buffer_pool keep), partition part_other values less than (maxvalue) )
可使用alter table修改分区的物理属性
alter table log modify partition part_2016_3 storage(buffer_pool keep);
间隔分区是从oracle 11gr1开始新增长的一个特性,以一个分区为起点,设置一个规则(间隔),让oracle根据该规则知道之后该怎么增长分区。这样就不须要预先设置好全部的分区了,oracle在插入数据时知道本身去建立分区。间隔分区的键值应该是能够和number、interval进行相加的列。
对于任何合适的现有区间分区表,均可以使用alter table修改成间隔区间分区表。
语法
partition by range (column_name) interval (expr) store in (tablespace1,tablespace2,....) (partition name1 values less than (value1), partition name2 values less than (valuee2), ....);
通常间隔分区只需建立一个起始分区便可.
create table log ( text varchar2(255), rksj date ) pctfree 20 storage(buffer_pool default) partition by range(rksj) interval (numtoyminterval(1,'month')) ( partition part_2016_3 values less than (to_date('2016-3-1','yyyy-mm-dd')) )
11g开始oracle增长了interval分区,和range分区最大的区别就是它会根据数据自动去建立分区。
可是它有如下缺点
1. 第一个分区不能删除,由于它是参考,删除会报ora-14758错误。
2. 分区没有便于管理的名称
3. 若是建立索引时指定了多个分区,则这些分区之间是不会应用interval继续分区了。只有大于这其中的值才会开始分区
4. 不能执行分区的循环使用??
ora-14758错误解决方法
先将间隔分区表转化为普通range分区表
alter table table_name set interval ();
删除指定分区后再将间隔设置回来
alter table table_name set interval (numtodsinterval(1,’DAY’));
散列分区是在一个列或者多个列上引用散列函数,行会按散列值放到不一样的分区上去。oracle建议分区数应该是2的一个幂次方(2,4,8,16,。。。)。
散列分区的目的是让数据很好的分布在多个不一样的设备上,或者将数据汇集到更可管理的块上,因此散列键应该是惟一的列或者至少有足够的相异值。以便数据能在多个分区上均匀的分布。
partition by hash (column1,column2,...) ( partition part1 tablespace ts_name1, partition part2, ..... )
其它物理属性不能在这里设置。
或者
partition by hash (column1,column2,...) partitions n store in (ts_name1,ts_name2,...);
create table log ( id number(10), text varchar2(255), rksj date ) partition by hash(id) ( partition part1 tablespace users , partition part2, partition part3 tablespace ts_test, partition part4 ); create table log ( id number(10), text varchar2(255), rksj date ) partition by hash(id) partitions 4 store in (users,ts_test);
根据离散的值决定数据该放在哪一个分区里。
partition by list(column1,...) ( partition part1 values (value1,value2), partition part2 values (value3,value4), ..... partition part_default (default) )
若是设置了default分区,则不能再增长分区了,只能删除default分区才能增长分区
create table data ( rawdata raw(200), status varchar2(1) ) partition by list(status) ( partition part_u values ('u') tablespace users storage(buffer_pool keep), partition part_p values ('p')tablespace ts_test, partition part_def values (default) );
引用分区是oracle 11gr1引入的新特性,要以某种方式
对子表进行分区,使得子表的分区和父表的保持一对一的关系。
create table orders ( order# number(10) primary key, order_date date, data varchar2(100) ) partition by range(order_date) ( partition part_2015 values less than (to_date('2016-1-1','yyyy-mm-dd')), partition part_2016 values less than (to_date('2017-1-1','yyyy-mm-dd')) ); create table order_items ( order# number(10), item# number(10), price number(5,2), description varchar2(200), constraint pk_order_items primary key(order#,item#), constraint fk_order_items foreign key(order#) references orders(order#) ) partition by reference (fk_order_items);
的range,list和hash分区,在这些分区的基础上再进行分区。
每种分区均可以进行range,list和hash子分区。
例子
在区间分区的基础上散列分区
create table log ( id number(10), text varchar2(200), logtime date, type varchar2(1) ) partition by range(logtime) subpartition by hash(id) subpartitions 10 store in (users,ts_test) (partition part_2015 values less than (to_date('2016-1-1','yyyy-mm-dd')), partition part_2016 values less than (to_date('2017-1-1','yyyy-mm-dd')) ); 区间分区上列表分区 create table log ( id number(10), text varchar2(200), logtime date, type varchar2(1) ) partition by range(logtime) subpartition by list(type) subpartition template ( subpartition part_a values ('A') tablespace users, subpartition part_b values ('B') tablespace ts_test, subpartition part_cd values ('C','D') tablespace users ) (partition part_2015 values less than (to_date('2016-1-1','yyyy-mm-dd')), partition part_2016 values less than (to_date('2017-1-1','yyyy-mm-dd')) ); create table log ( id number(10), text varchar2(200), logtime date, type varchar2(1) ) partition by hash(id) subpartition by list(type) subpartition template ( subpartition part_a values ('A') tablespace users, subpartition part_b values ('B') tablespace ts_test, subpartition part_cd values ('C','D') tablespace users ) partitions 8 store in (users,ts_test) ;
聚簇表的理念是将数据按照咱们想要的方式(聚簇)将多个表预联结在一块儿,即放在同一个块上。聚簇也可用于单个表,按某个列
将数据分组存储。
create cluster emp_dept_cluster (deptno number(2)) size 1024; select dbms_metadata.get_ddl('CLUSTER','EMP_DEPT_CLUSTER') from dual; DBMS_METADATA.GET_DDL('CLUSTER','EMP_DEPT_CLUSTER') -------------------------------------------------------------------------------- CREATE CLUSTER "SCOTT"."EMP_DEPT_CLUSTER" ( "DEPTNO" NUMBER(2,0) ) SIZE 1024 PCTFREE 10 PCTUSED 40 INITRANS 2 MAXTRANS 255 STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "USERS" PARALLEL (DEGREE 1 INSTANCES 1)
其中size是聚簇最重要的一个参数,意思是每一个键值大概关联多大的空间,这里是1024B,对于大小为8KB的块能够放下7个键。若是设置的太大会浪费空间,若是设置过小又会过分串链,违背了聚簇就是为了将相关数据放在一块儿的本意。
向聚簇中放数据以前,首先要为聚簇建立索引,而后就能够建立聚簇表了。聚簇索引的任务就是拿到一个键值,而后返回包含这个键值的块地址。
create index idx_emp_dept_cluster on cluster emp_dept_cluster; create table dept (deptno number(2), dname varchar2(20), loc varchar2(20)) cluster emp_dept_cluster(deptno); create table emp ( empno number(10) primary key, name varchar2(20), mgr number(10), sal number(8,2), deptno number(2) ) cluster emp_dept_cluster(deptno);
聚簇表没有tablespace这些段属性,由于这些属性都在聚簇上定义。
主要用于读,且经过索引来读,另外会频繁的把信息联结起来使用。
基本和索引聚簇表同样,就是将索引换成了散列函数。oracle获取一列的值,经过散列函数获得一个值,而后经过这个值得到数据所在的块。使用散列的缺点是没法进行 扫描,只要是范围扫描则必须执行全表扫描。
散列聚簇表的块数是预先分配好的。由散列聚簇表的hashkeys和size加上块的大小获得,即trunc(hashkeys*size/blocksize)
create cluster hash_cluster (hash_key number(10) ) hashkeys 10000 size 8192 tablespace users; create table hash_table1 ( x number(10),name varchar2(10) ) cluster hash_cluster(x); create table hash_table2 ( x number(10),loc varchar2(10) ) cluster hash_cluster(x);
散列聚簇表还可使用单表散列聚簇表
create cluster hash_cluster
(hash_key number(10)
)
hashkeys 10000
size 8192
single table
tablespace users;
用于保存事务或者会话期间的中间结果。临时表中保存的数据只对当前会话可见,分为两种状况,一种是事务一结束数据就被清空。一种是事务结束后依然存在。使用临时表生成的redo数据要少。
create global temporary med
(name varchar2(10),
phone varchar2(20)
)
on commit delete rows;
create global temporary med (name varchar2(10), phone varchar2(20) ) on commit preserve rows;