更多精彩内容请光临
www.leonarding.com
《
Oracle
数据结构知多少(二)
》
一 开场白
上周刚刚完成了“ Oracle 数据结构(一)”,重点讲述了数据块的存储属性,空闲空间合并, segment-extent-block 相互关系等,主要说明了 extent和 block在数据库上的作用和为什么要这么设置。
感兴趣的朋友,浏览《Oracle 数据结构知多少(一)》 http://space.itpub.net/26686207/viewspace-757937
本周又要继续开始“ Oracle 数据结构系列之二”重点讲述表空间的存储属性,数据块的压缩,段空间存储属性等知识,欢迎广大亲们一起交流讨论,营造一个专家圈子,一起更上一层楼。长话短说,进入正题。我们在上一节已经把 segment-extent-block概念一一讲明了,这里呢我们主要讲一讲它们在生产库上应用场景和如何设置
二 数据库版本
LEO1@LEO1>select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux:Version 11.2.0.1.0 - Production
NLSRTL Version11.2.0.1.0 - Production
三 实验
1.创建表,分区表,大对象字段,分别查询出它们是否为段对象,给出 SQL演示的整个过程。
段对象: Oracle所有分配存储空间的对象都叫段对象。例如 表 索引 分区 大对象等都称之为段对象
段对象是接近于应用层的,它是业务层面的一个含义,表空间逻辑上是由段对象组成的。
段的种类
数据段
LEO1@LEO1>create table t1 (x int,y int); 创建个表
Table created.
LEO1@LEO1>create index idx_t1 on t1(x); 表上创建个索引
Index created.
LEO1@LEO1>insert into t1 values(1,1); 只有插入数据后oracle才会真正创建索引
1 row created.
LEO1@LEO1>commit;
Commit complete.
LEO1@LEO1>select * from t1;
X Y
----------------------------------
1 1
select segment_name,segment_type,tablespace_name,extents,blocks,bytes/1024/1024from dba_segments where segment_name in ('T1','IDX_T1');
SEGMENT_NAMESEGMENT_TYPE TABLESPACE_N EXTENTS BLOCKS BYTES/1024/1024
------------------------------------------ ------------------ ------------------------------- ------------------------------
T1 TABLE LEO1 1 8 .0625
IDX_T1 INDEX LEO1 1 8 .0625
上面的表和索引都占用空间(多少extent block 容量),因此都可称为段对象
临时段
是临时表和中间状态的数据存储放的位置,常用于sort hash merge,不用永久保存,只做临时存储,临时段组成了临时表空间,只有在内存不够时,oracle才会在临时表空间上创建临时段。
注意:临时段上的操作不产生redo,因为无需保护,是一种中间状态,这样可以提高效率
LEO1@LEO1>select file#,name,status,enabled,bytes,blocks,block_size from v$tempfile;
FILE# NAME STATUS ENABLED BYTES BLOCKS BLOCK_SIZE
--------------------------------------------------------------------------------------------------------------------------------
1 /u01/app/oracle/oradata/LEO1/temp01.dbf ONLINE READ WRITE 128974848 15744 8192
经过查看临时段也分配存储空间了,块大小8k,15744个块,大小为128974848字节,因此说临时表 索引啊都可以称之为段对象,临时表的使用和演示后面进行,敬请期待!
回滚段
《Oracleundo我们需要掌握什么》 http://space.itpub.net/26686207/viewspace-757488 这篇文章对undo段做了非常详细介绍,朋友们可以参考。
这里我们只是演示一下undo段所占用的空间
LEO1@LEO1>select tablespace_name,file_name,bytes/1024/1024,autoextensible fromdba_data_files where tablespace_name='UNDOTBS1';
TABLESPACE_N FILE_NAME BYTES/1024/1024 AUT
---------------------------------------------------------------------------------------------------------------------------------
UNDOTBS1 /u01/app/oracle/oradata/LEO1/undotbs01.dbf 165 YES
这就是undo表空间对应的undo数据文件,在数据库需要做回滚时就在undo表空间中创建undo段。
分区表的段对象
分区表中,一个分区对应一个段对象,如果有3个分区那么这张分区表就包含3个段对象,这时表已经不是段对象了,倒成了一个标签。
LEO1@LEO1>create tablespace par_data01 datafile size 10M autoextend off;
Tablespacecreated.
LEO1@LEO1>create tablespace par_data02 datafile size 10M autoextend off;
Tablespacecreated.
LEO1@LEO1>create tablespace par_data03 datafile size 10M autoextend off;
Tablespacecreated.
创建三个表空间分别存储三个分区
LEO1@LEO1>create table part_leo (name varchar2(20),age number,part_date date);
Table created.
LEO1@LEO1>insert into part_leo values ('leonarding1',100,to_date('2001-01-01','yyyy-mm-dd'));
insert intopart_leo values ('leonarding2',200,to_date('2002-02-02','yyyy-mm-dd'));
insert intopart_leo values ('Alan1',300,to_date('2003-03-03','yyyy-mm-dd'));
insert intopart_leo values ('Alan2',400,to_date('2004-04-04','yyyy-mm-dd'));
insert intopart_leo values ('tigerfish1',500,to_date('2005-05-05','yyyy-mm-dd'));
insert intopart_leo values ('tigerfish2',600,to_date('2006-06-06','yyyy-mm-dd'));
LEO1@LEO1>commit;
Commit complete.
LEO1@LEO1>select * from part_leo;
NAME AGE PART_DATE
--------------------------------- ---------
leonarding1 100 01-JAN-01
leonarding2 200 02-FEB-02
Alan1 300 03-MAR-03
Alan2 400 04-APR-04
tigerfish1 500 05-MAY-05
tigerfish2 600 06-JUN-06
创建一个表并插入6行记录,做分区表的原表
LEO1@LEO1>CREATE TABLE part_leo_super
PARTITION BY RANGE (part_date)
( PARTITION p1 VALUES LESS THAN(to_date('2002-12-01','yyyy-mm-dd'))
TABLESPACE par_data01, 比2002-12-01小的记录放入p1分区
PARTITION p2 VALUES LESS THAN(to_date('2004-12-01','yyyy-mm-dd'))
TABLESPACE par_data02, 比2004-12-01小的记录放入p2分区
PARTITION p3 VALUES LESS THAN(to_date('2006-12-01','yyyy-mm-dd'))
TABLESPACE par_data03, 比2006-12-01小的记录放入p3分区
PARTITION other VALUES LESS THAN(maxvalue)
TABLESPACE par_data03) 余下的记录放入 par_data03分区
as select * from part_leo; 2 3 4 5 6 7 8 9 10 11
Table created.
采用CTAS方式创建分区表,三个分区分别存放在三个表空间上
LEO1@LEO1>select * from part_leo_super partition (p1); 第一分区的数据
NAME AGE PART_DATE
--------------------------------- ---------
leonarding1 100 01-JAN-01
leonarding2 200 02-FEB-02
LEO1@LEO1>select * from part_leo_super partition (p2); 第二分区的数据
NAME AGE PART_DATE
--------------------------------- ---------
Alan1 300 03-MAR-03
Alan2 400 04-APR-04
LEO1@LEO1>select * from part_leo_super partition (p3); 第三分区的数据
NAME AGE PART_DATE
--------------------------------- ---------
tigerfish1 500 05-MAY-05
tigerfish2 600 06-JUN-06
LEO1@LEO1>select segment_name,partition_name,tablespace_name,extents,blocks,bytes/1024/1024from dba_segments where segment_name='PART_LEO_SUPER';
SEGMENT_NAME PARTITION_NAME TABLESPACE_N EXTENTS BLOCKS BYTES/1024/1024
----------------------------------------------------------------------------------------------------------------------------------------
PART_LEO_SUPER OTHER PAR_DATA03 1 8 .0625
PART_LEO_SUPER P1 PAR_DATA03 1 8 .0625
PART_LEO_SUPER P2 PAR_DATA03 1 8 .0625
PART_LEO_SUPER P3 PAR_DATA03 1 8 .0625
每个分区都有独立的存储空间,因此可以说每个分区都是一个段对象(PARTITION_NAME)PART_LEO_SUPER这个名在分区表中不算段名了可以看成一个总名称!
大对象字段的段对象
我们为什么要创建大对象字段,普通的varchar2字段:最大支持4000个字符!
如果我们想在字段中存放一篇小说,一个文章,一篇blog怎么办?大对象字段就是解决这个问题的。
注:大对象与小对象字段的长度不一致导致碎片的一个原因,一般把大对象单独放在一个表空间中减少碎片的产生。
创建存放CLOB字段的表空间clob_data
LEO1@LEO1>create tablespace clob_data datafile size 10M autoextend off;
Tablespacecreated.
创建含CLOB(character large object)字段表
LEO1@LEO1>create table clob_table
(
name varchar2(20), 姓名
employment varchar2(30), 职业
school varchar2(30), 毕业院校
current_date date, 当前时间
discription clob 描述(字符型大对象字段)
)
tablespace leo1 存放于leo1表空间
lob (discription) 指定大对象字段
store as
(
tablespace clob_data 大对象存放的表空间
);
2 3 4 5 6 7 8 9 10 11 12 13 14
Table created.
我们通过下列数据字典找到刚刚创建的大对象
LEO1@LEO1>select table_name,column_name,segment_name,tablespace_name from dba_lobs wheretable_name='CLOB_TABLE';
TABLE_NAME COLUMN_NAME SEGMENT_NAME TABLESPACE_N
--------------------------------------------------------------------------------------------------------------------
CLOB_TABLE DISCRIPTION SYS_LOB0000074408C00005$$ CLOB_DATA
小结:由此看来大对象字段也占用表空间,凡是占用空间的对象都可称为段对象。
2.分别创建一个 ASSM, MSSM管理的表空间。
MSSM―ManualSegment Space Management 手动段空间管理(手动设置对象的存储属性)
这种管理方式就是使用freelist管理数据块的分配和回收,是一种只针对数据块分配的管理方式,这种方式可以让DBA有更大的空间管理余地,更大自由发挥空间,在早期的Oracle上都是通过这种方式管理块分配的。
场景:对于一些数据块操作非常敏感的场合相对适用
参数:MSSM-由你设置freelists、freelistgroups、pctused、pctfree、initrans等参数来控制如何分配、使用段中的空间
缺点:1.需要设置更多的参数,例如上面所写的参数,操作复杂度更强
2.参数设置值比较难评估,需要大量的测试过程
3.需要了解数据库体系结构的DBA设置
注意:1.freelist空闲列表是放在段头里面的,如果有多个用户同时访问列表势必会引发段头争用,导致“buffer busy waits”等待事件发生,建议多设几个freelist,防止争用。
ASSM―AutomaticSegment Space Management 自动段空间管理(自动设置对象的存储属性)
这种管理方式就是使用“位图bitmap”管理数据块的分配和回收,1为占用块不可分配,0为空闲块可分配,由于计算机就是由二进制编码的,所以操作二进制代码是非常快捷的。现在Oracle 10g 11g 默认值都是ASSM段空间管理方式。
场景:希望数据块由Oracle自动分配管理的场合,不需要DBA介入太多
参数:ASSM-你只需控制一个参数pctfree,其他参数由Oracle自动管理,如果强行设置也将被忽略。
三层位图模式管理段空间:第一层BMB(bit map block)记录每个extent中数据块的存储信息,只管理当前的extent内块,放在extent头中,这是leaf节点
第二层BMB管理第一层BMB记录,这是branch节点
第三层BMB管理第二层BMB记录,放在段头中,这是root节点
ASSM段头包含了每个Extent存储信息
Extent区头包含BMB信息
优点:1.自动化管理段空间,无需手动设置大量参数,简化了操作
2.增大并发度,由于ASSM没有freelist概念,也就没有freelist列表争用情况,也就没有段头争用的情况,提高资源利用率。
缺点:1.全表扫描性能没有MSSM模式下好
2.大数据加载,会导致性能下降,因为要自动维护位图表,需要一定的开销
3.影响索引的集群因子(clustering factor)
(1) 设置db_create_file_dest参数
作用:指定Oracle创建某某文件的存放路径,设置后就可以在创建表空间时不指定文件路径了。
■ Datafiles
■ Tempfiles
■ Redo log files
■ Control files
■ Block change tracking files
LEO1@LEO1> showparameter db_create_file_dest
NAME TYPE VALUE
----------------------------------------------- ------------------------------
db_create_file_dest string
空,我们现在还没有初始化这个参数值
LEO1@LEO1>alter system set db_create_file_dest='/u01/app/oracle/oradata/LEO1/';
System altered.
LEO1@LEO1> showparameter db_create_file_dest
NAME TYPE VALUE
----------------------------------------------- ------------------------------
db_create_file_dest string /u01/app/oracle/oradata/LEO1/
现在我们已经设置好了参数
(2)创建MSSM和ASSM表空间
LEO1@LEO1>create tablespace leo_mssm segment space management manual;
Tablespacecreated.
LEO1@LEO1>create tablespace leo_assm segment space management auto;
Tablespacecreated.
我们创建了一个MSSM段管理表空间又创建一个ASSM段管理表空间,默认大小100M
LEO1@LEO1>select file#,name,bytes/1024/1024 from v$datafile;
FILE# NAME BYTES/1024/1024
----------------------------------------------------------------------------------------------------------------------------------------------
9 /u01/app/oracle/oradata/LEO1/LEO1/datafile/o1_mf_leo_mssm_8p9jorpx_.dbf 100
10 /u01/app/oracle/oradata/LEO1/LEO1/datafile/o1_mf_leo_assm_8p9jplb8_.dbf 100
数据文件名是系统自定义的。
LEO1@LEO1>select tablespace_name,segment_space_management from dba_tablespaces wheretablespace_name in ('LEO_MSSM','LEO_ASSM');
TABLESPACE_N SEGMEN
----------------------------------
LEO_ASSM AUTO
LEO_MSSM MANUAL
小结:我们根据实际需要来创建与业务匹配的表空间,宗旨技术为业务服务。
3.验证段存储属性和所在表空间存储属性的关系,给出SQL演示,并得出结论。
表空间存储属性依赖于段属性,段存储属性依赖于数据块属性
表空间管理方式
本地管理表空间(Locally Managed Tablespace):表空间存储信息写在数据文件头中,其中段空间管理方式又分为ASSM和MSSM,这是oracle 默认的管理方式
好处:自动监控表空间上数据变化并进行调整
避免通过查询数据字典获得表空间的存储信息,可以直接在数据文件头中查询,提高效率
创建表空间的时候使用关键字extent management local
字典管理表空间(Dictionary Managed Tablespace):表空间存储信息写在数据字典中,所有对表空间的操作都要先对数据字典(system表空间)进行操作效率较低,现在已经不在用这种方式了。
创建表空间的时候使用关键字 extent management dictionary
LEO1@LEO1>create tablespace local_manager datafile size 10m extentmanagement local;
Tablespacecreated.
LEO1@LEO1>create tablespace dictionary_manager datafile size 10m extent managementdictionary;
create tablespacedictionary_manager datafile size 10m extent management dictionary
*
ERROR at line 1:
ORA-12913: Cannotcreate dictionary managed tablespace
LEO1@LEO1>select tablespace_name,extent_management from dba_tablespaces wheretablespace_name in ('LOCAL_MANAGER','DICTIONARY_MANAGER');
TABLESPACE_NAME EXTENT_MAN
----------------------------------------
LOCAL_MANAGER LOCAL
O~MY GOD11.2.0.1.0 版本只能创建“本地管理表空间”不在允许创建“字典管理表空间”了,现在已经不用这种方式了,good 没的选,我们继续吧!
段管理方式
段空间管理方式:数据块的分配与回收是由位图管理 or FREELIST管理,这和extent管理方式没关系
自动段空间管理ASSM:通过位图方式管理段空间(位图存放在段头) 关键字segment space management auto(默认方式)
手动段空军管理MSSM:通过FREELIST方式管理段空间(FREELIST存放在段头,如果多个用户同时访问列表的话建议Freelist可设多个防止latch争用) 关键字segment space management manual
LEO1@LEO1>create tablespace assm_leo datafile size 10m segmentspace management auto;
Tablespacecreated.
LEO1@LEO1>create tablespace mssm_leo datafile size 10m segmentspace management manual;
Tablespacecreated.
LEO1@LEO1>select tablespace_name,extent_management,segment_space_management fromdba_tablespaces where tablespace_name in ('ASSM_LEO','MSSM_LEO');
TABLESPACE_NAME EXTENT_MAN SEGMEN
---------------------------------------- ---------------------------------- ----------
ASSM_LEO LOCAL AUTO
MSSM_LEO LOCAL MANUAL
默认都是“本地管理表空间”,第一个表空间是ASSM方式,第二个表空间是MSSM方式。
Extent管理(这和数据块管理方式没有关系),只是说明extent应该用什么方式扩展
Autoallocate:系统自动分配区大小,分配的值不固定
Uniform:手动统一分配区大小,分配的值固定
LEO1@LEO1>create tablespace auto_leo datafile size 10m autoallocate;
Tablespacecreated.
LEO1@LEO1>create tablespace uniform_leo datafile size 10m uniform size 2m;
Tablespacecreated.
LEO1@LEO1>selecttablespace_name,initial_extent,next_extent,min_extents,max_extents,allocation_typefrom dba_tablespaces where tablespace_name in ('AUTO_LEO','UNIFORM_LEO');
TABLESPACE_NAME INITIAL_EXTENT NEXT_EXTENT MIN_EXTENTSMAX_EXTENTS ALLOCATIO
-------------------------------------------- ----------- ----------- ----------- ---------
AUTO_LEO 65536 1 2147483645 SYSTEM
UNIFORM_LEO 2097152 2097152 1 2147483645 UNIFORM
SYSTEM:系统自动分配区大小,分配值不固定
UNIFORM:手动统一分配区大小,每次固定分配2M
INITIAL_EXTENT:初始化区大小2M,在auto模式下只有初始化区大小,下次分配值不固定
NEXT_EXTENT:下次分配区大小2M,在uniform模式下这两个参数值一样
MIN_EXTENTS:最小区个数
MAX_EXTENTS:最大区个数
4.SQL演示临时表的机制,并说明它的适用场合
临时表:这个东东在我们日常工作中用的可能相对不多,但它的作用有时是无法代替的,在某些场景下临时表可以提高大大的效率,俗话说好钢用到刀刃上。临时表也是临时段的一种,因为它也需要放到临时表空间里。
特性:1.临时表的回收和扩展效率要高一点,因为它不会产生redo,是一种中间状态
2.临时表结构与属性和普通表一样
3.临时表也可以创建索引
4.临时表只存在于某个会话或事务的生命周期里,临时表中数据只对当前会话可见
5.基于事务临时表:当临时表上某个事务提交/回滚后,自动清空临时表数据(delete rows)
6.基于会话临时表:当临时表的会话结束后,自动清空临时表数据(preserve rows)
场景:临时表常被用于存放操作的中间状态(数据处理的中间环节)例如 order by hash merge
会话147基于事务临时表测试(Oracle默认是事务)
LEO1@LEO1>select distinct sid from v$mystat;
SID
-----------------
147
LEO1@LEO1> droptable leo8 purge; 清空环境
Table dropped.
LEO1@LEO1> droptable leo9 purge; 清空环境
Table dropped.
创建基于事务临时表
LEO1@LEO1>create global temporary table leo8 on commit deleterows as select * from dba_objects;
Table created.
LEO1@LEO1>select count(*) from leo8;
COUNT(*)
----------
0
记录数为0这是为神马呢,原来这与基于事务临时表特性有关,当事务提交/回滚后立刻清空表,而恰恰DDL操作会隐含一个commit动作自动提交,从而触发了清空临时表数据的动作,我们才看到记录数为0。
LEO1@LEO1>insert into leo8 select * from dba_objects; 我们插入71976行
71976 rowscreated.
LEO1@LEO1>select count(*) from leo8; 此时我们已经看到有记录数了
COUNT(*)
----------
71976
LEO1@LEO1>commit; 根据基于事务临时表特性,只要提交事务后就会立即清空表数据
Commit complete.
LEO1@LEO1>select count(*) from leo8; 现在是空表了
COUNT(*)
----------
0
会话153基于会话临时表测试
LEO1@LEO1>select distinct sid from v$mystat;
SID
-----------------
153
创建基于会话临时表
LEO1@LEO1>create global temporary table leo9 on commit preserverows as select * from dba_objects;
Table created.
LEO1@LEO1>select count(*) from leo9;
COUNT(*)
----------
71976
基于会话临时表不会跟着事务提交而自动清空,必须退出会话后才清空表,因此我们看到是有记录数的。
LEO1@LEO1>insert into leo9 select * from dba_objects; 插入数据
71976 rowscreated.
LEO1@LEO1>select count(*) from leo9; 记录数翻了一番
COUNT(*)
----------
143952
LEO1@LEO1>commit; 根据基于会话临时表特性,提交事务不清空表数据
Commit complete.
LEO1@LEO1>select count(*) from leo9; 记录数依然存在完好无损
COUNT(*)
----------
143952
LEO1@LEO1> exit 退出会话,当临时表的会话结束后,立即清空表数据
[oracle@leonarding1~]$ sqlplus leo1/leo1 重新登陆
LEO1@LEO1>select count(*) from leo9; 现在是空表了
COUNT(*)
----------
0
临时表索引创建测试
临时表也可以创建索引的,创建的索引和普通索引一样具有高效的检索功能,只是临时表索引会放在临时表空间中,在user_indexes数据字典视图中是查不到的。
我们给临时表leo9的object_id列上创建一个索引idx_leo9
LEO1@LEO1> droptable leo9 purge;
Table dropped.
LEO1@LEO1>create global temporary table leo9 on commit preserve rows as select * fromdba_objects;
Table created.
LEO1@LEO1>create index idx_leo9 on leo9(object_id);
create indexidx_leo9 on leo9(object_id)
*
ERROR at line 1:
ORA-14452:attempt to create, alter or drop an index on temporary table already in use
摊上事了,摊上大事了!ORA-14452:企图创建索引,修改或删除一个索引时在临时表上已经被使用
这是怎么回事不让创建临时索引,并且这是一个新表并没有索引存在
LEO1@LEO1>select object_id from user_objects where object_name in ('LEO9','IDX_LEO9');
OBJECT_ID
------------------
74414
LEO1@LEO1>select * from v$lock where id1=74414;
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
-------------------------------- ---------- -- ---------- ---------- ---------- -------------------- ----------
000000007D85A8F8000000007D85A950 142 TO 74414 1 3 0 2435 0
发生这种情况极有可能对象被锁定了,我们检查一下v$lock视图,果不其然发现了一个3号锁,官方文档上说3号锁是一个行级排它锁,可以DML但不能DDL,原因找到,剩下就是解决。
3
Row Exclusive Table Lock(RX)
又叫(SX)
行级排他锁,通常已经有事务在修改行或者select…for update 修改结果集。允许其他事务对锁定的表进行select insert update delete 或 lock table 同时锁定一张表
Lock table t in row exclusive mode;
解决方案:退出会话再登录,让临时表清空所有数据,我们创建完临时索引后再插入数据即可。
LEO1@LEO1> exit 退出
Disconnected fromOracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With thePartitioning, OLAP, Data Mining and Real Application Testing options
[oracle@leonarding1~]$ sqlplus leo1/leo1 再登录
SQL*Plus: Release11.2.0.1.0 Production on Thu Apr 11 14:45:11 2013
Copyright (c)1982, 2009, Oracle. All rights reserved.
Connected to:
Oracle Database11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With thePartitioning, OLAP, Data Mining and Real Application Testing options
LEO1@LEO1>create index idx_leo9 on leo9(object_id); 临时索引成功创建
Index created.
LEO1@LEO1>select object_id,object_name,object_type,status,temporary from user_objectswhere object_name in ('LEO9','IDX_LEO9');
OBJECT_ID OBJECT_NAME OBJECT_TYPE STATUS T
--------------------------------------------------------------------------------
74418 IDX_LEO9 INDEX VALID Y
74414 LEO9 TABLE VALID Y
我们在user_objects视图上可以看到临时表和临时索引的状态都是有效的,临时标记=Y
LEO1@LEO1>select table_name,tablespace_name from user_tables where table_name='LEO9';
TABLE_NAME TABLESPACE_NAME
------------------------------------------------------------
LEO9
LEO1@LEO1>select index_name,tablespace_name from user_indexes whereindex_name='IDX_LEO9';
INDEX_NAME TABLESPACE_NAME
------------------------------------------------------------
IDX_LEO9
LEO1@LEO1>select segment_name,tablespace_name from user_segments where segment_name in('LEO9','IDX_LEO9');
no rows selected
我们在user_tables user_indexes user_segments 这3个视图上是查不到leo9和idx_leo9的信息的,这是为什么呢?
答:它们只记录数据段上的对象,对于临时段和回滚段上的对象都不记录,由于临时表和临时索引都是放在临时表空间上面的,因此查询不到是正常的。
小结:要谨记临时表的特性,数据只保存在一个会话或者一个事务的周期中,会话结束或者事务结束都会清空表数据,默认创建的临时表是基于事务的。
5.示例演示数据压缩的效果
数据压缩是一个源远流长的话题,在SAP SYBASE MYSQL NOSQL领域中都会看到它的身影,经常会听到我们要压缩,我们要压缩,数据压缩之后有什么什么好处等等!往往大家在用到某一个技术的时候经常会看到它的好处殊不知任何东东都有其双面性,数据压缩也一样。我们先来看看它的应用场合
1.可以节约我们的存储空间,这是大家经常会想到的理由
2.相同数据总量下,会减少处理的数据块
包括内存占用
I/O提速
查询提速
例如300个数据块压缩成100数据块,理论上效率会提高三倍!
3.数据压缩使用的是一套“替换算法”,就是把相同的字符串用一个标签代替,简单的说就是一个去重的过程,使存在的字符总量减少达到总体容量减小的目的,记录中重复数据越多压缩效果越好,如果没有重复数据就不会压缩。
4.OLAP系统中常用,一次性把数据加载入库,如果没有后续的DML操作,那么查询起来是非常高效的。如果数据会频繁的增删改查,频繁压缩解压定会消耗更多的资源和时间,尤其是CPU资源!
实验
LEO1@LEO1>create table leo10 compress as select * fromdba_objects; 压缩的表
Table created.
LEO1@LEO1>create table leo11 as select * from dba_objects; 没有压缩的表
Table created.
LEO1@LEO1>select segment_name,tablespace_name,extents,blocks,bytes from dba_segmentswhere segment_name in ('LEO10','LEO11');
SEGMENT_NAME TABLESPACE_NAME EXTENTS BLOCKS BYTES
--------------------------------------------- ---------- ---------- ---------------------------------------- ---------- ----------
LEO10 LEO1 18 384 3145728
LEO11 LEO1 24 1152 9437184
从分配的extents blocks bytes 指标上一眼就可以看出空间减少了3倍,效果出众,毋庸置疑,这是因为在object_type owner等字段上存在大量重复数据。
我们来看一下如何解压表数据
LEO1@LEO1>select table_name,compression from dba_tables where table_name in('LEO10','LEO11');
TABLE_NAME COMPRESS
--------------------------------------
LEO10 ENABLED 压缩版
LEO11 DISABLED 非压缩版
LEO1@LEO1>alter table leo10 nocompress; 解压leo10
Table altered.
LEO1@LEO1>select table_name,compression from dba_tables where table_name in('LEO10','LEO11');
TABLE_NAME COMPRESS
--------------------------------------
LEO10 DISABLED 完成解压
LEO11 DISABLED
LEO1@LEO1>select segment_name,tablespace_name,extents,blocks,bytes from dba_segmentswhere segment_name in ('LEO10','LEO11');
SEGMENT_NAME TABLESPACE_NAME EXTENTS BLOCKS BYTES
--------------------------------------------- ---------- ---------- ----------
LEO10 LEO1 18 384 3145728
LEO11 LEO1 24 1152 9437184
leo10解压后的数据存储属性和以前没变化(原数据块没有被释放),只对以后插入的数据生效。
如果你想解压后立刻释放数据块可以采用 move 方式
LEO1@LEO1> alter table leo11 move compress; leo11 压缩
Table altered.
LEO1@LEO1>select segment_name,tablespace_name,extents,blocks,bytes from dba_segmentswhere segment_name in ('LEO10','LEO11');
SEGMENT_NAME TABLESPACE_NAME EXTENTS BLOCKS BYTES
--------------------------------------------- ---------- ---------- ----------
LEO10 LEO1 18 384 3145728
LEO11 LEO1 18 384 3145728
立刻压缩
LEO1@LEO1> alter table leo11 move nocompress; leo11 解压
Table altered.
LEO1@LEO1>select segment_name,tablespace_name,extents,blocks,bytes from dba_segmentswhere segment_name in ('LEO10','LEO11');
SEGMENT_NAME TABLESPACE_NAME EXTENTS BLOCKS BYTES
--------------------------------------------- ---------- ---------- ----------
LEO10 LEO1 18 384 3145728
LEO11 LEO1 23 1024 8388608
立刻释放
Move原理:就是把数据块打散重新分配,重新整理,重新排序,要比直接压缩/解压消耗CPU I/O资源,好处就是立竿见影。根据业务需求来设置吧!呼哈哈
表空间级压缩
答:1.如果创建一个具有压缩属性的表空间,那么在此表空间上所有对象都自动继承压缩属性。
2.可以在表空间级别上定义COMPRESS属性,既可以在生成时利用CREATE TABLESPACE来定义,也可以稍后利用ALTER TABLESPACE来定义。
3.可以在一个表空间直接压缩或解压一个表,而无需考虑表空间级别上的COMPRESS属性。
现在创建一个压缩表空间并检查其压缩属性
LEO1@LEO1>create tablespace compress_leo1 datafile size 10M default compress;
Tablespacecreated.
LEO1@LEO1>select tablespace_name,def_tab_compression from user_tablespaces where tablespace_name='COMPRESS_LEO1';
TABLESPACE_NAME DEF_TAB_
--------------------------------------
COMPRESS_LEO1 ENABLED
使现有表空间转换为压缩表空间
alter tablespacecompress_leo1 nocompress;
alter tablespacecompress_leo1 compress;
我们在COMPRESS_LEO1表空间上创建一个表看看是否自动继承压缩属性
LEO1@LEO1>create table comp_leo tablespace compress_leo1 as select * from dba_objects;
Table created.
LEO1@LEO1>select table_name,compression from dba_tables where table_name in ('COMP_LEO');
TABLE_NAME COMPRESS
--------------------------------------
COMP_LEO ENABLED
表创建后自动成为压缩版
段对象 ASSM MSSM 临时表 临时索引 压缩表空间 uniform autoallocate
Leonarding
2013.4.13
天津 &spring
分享技术 ~ 成就梦想
Blog :www.leonarding.com