段:segment
一个段建立以后,oracle会给它分配一个区,这个区一般是8个块(空块)。
em建立表空间:
创建表空间要考虑的事项有:
1:数据文件个数
2:段的管理方式
自动:表空间中的对象将自动管理其空闲空间,这将提高空闲空间管理性能(毫无疑问选择自动管理)
手动:表空间中的对象将使用空闲列表来管理其空闲空间,这是为了确保向后兼容
3:区的管理方式
本地管理(毫无疑问选择本地管理)
选择本地管理后,区的分配方式可以设置为(自动,统一)一般选择自动
字典管理
4:表空间的状态(读写,只读,脱机)
5:表空间的类型(永久,temp,undo)
6:是否启动事件日志(redolog),一般选择启动。
访问:localhsot:1158/em
![](https://app.yinxiang.com/shard/s14/res/4f1fca7c-b746-4b3f-8a47-700e031d9f82.png?resizeSmall&width=786)
登录后进入(管理)->(表空间)-(创建)
![](https://app.yinxiang.com/shard/s14/res/e46ba922-a6ee-4d90-ac93-e30cacd2a0ac.png?resizeSmall&width=786)
创建表空间需要给表空间指定数据文件,在右下角点击(添加)添加数据文件:
![](https://app.yinxiang.com/shard/s14/res/3ce44fff-d92d-4122-b622-7366f88b866d.png?resizeSmall&width=786)
点击确定后:
![](https://app.yinxiang.com/shard/s14/res/0cf80c36-99bd-4196-902a-84dddb03574c.png?resizeSmall&width=786)
通过em设置后,生成的sql语句为:
CREATE SMALLFILE TABLESPACE "DATA1"
DATAFILE '/u01/app/oracle/oradata/jiagulun/data1_01.dbf' SIZE 100M REUSE
AUTOEXTEND ON NEXT 100M MAXSIZE UNLIMITED
LOGGING
EXTENT MANAGEMENT LOCAL
SEGMENT SPACE MANAGEMENT AUTO
意思为创建表空间名称为:data1
数据文件为:/u01/app/oracle/oradata/jiagulun/data1_01.dbf,数据文件大小为100m,重用数据文件
表空间自动扩展(AUTOEXTEND ON) ,每次扩展大小100M (NEXT 100M) ,最大扩展,不限制(UNLIMITED)
启动redolog(LOGGING)
区管理方式为本地(EXTENT MANAGEMENT LOCAL)
段管理方式为 自动(SEGMENT SPACE MANAGEMENT AUTO)
查询一个段的信息:v$segments;user_tables
select segment_name,blocks,extents,bytes,segment_type,tablespace_name from dba_segments where segment_name = 'T2';
![](https://app.yinxiang.com/shard/s14/res/86e211c0-3edf-4256-ae7e-84656fe3f6a1.png?resizeSmall&width=786)
segment_name:段的名称
blocks:有384个块
extents:有18个区
bytes:段大小
segment_type:段类型
tablespace_name:段对应的表空间
blocks和extents和bytes,3个字段的值不是实时的反应段的使用情况的。需要统计分析后才会准确一些。
对表进行分析,使blocks和extents和bytes准确:
analyze table t2 compute statistics
或者
exec dbms_stats.gather_table_stats('SYS','T2')
查看表的使用情况:
select table_name,num_rows,blocks,empty_blocks,avg_space,chain_cnt,avg_row_len from user_tables where table_name = 'T2'
![](https://app.yinxiang.com/shard/s14/res/92c4491d-85d4-4264-aed3-526b0ad9272d.png?resizeSmall&width=786)
table_name 表名
num_rows:表有多少行
blocks:表中数据所占的数据块数
empty_blocks:表中的空块数
avg_space:数据块中平均的使用空间(平均每个块908字节)
chain_cnt:表中行连接和行迁移的数量
avg_row_len:每条将记录的平均长度
查看区相关的信息:v$extents
select * from dba_extents where segment_name = 'T2';
![](https://app.yinxiang.com/shard/s14/res/21ac8bcf-5dc9-4bca-ac47-49ae2b12dc34.png?resizeSmall&width=786)
extent_id:是区的编号,上面查询说明了该段分配了0~17编号的区,共18个区
file_id:区所在的文件,上面查询说明了这些区都在1号文件上(dba_data_files)
block_id:起始块id ,上面的查询中0号区的起始块id是61433
blocks:总共块数,上面的查询中0号区的分配了8个块,因为oracle发现分的区太多,oracle会认为你这个段的数据会比较大,所以在第16个区的时候以下就分配了128个块,(这就是区的自动管理,如果是统一管理,那么一直都会是8个块)
高水位线的问题:
段使用分给他的区的最后一个块的位置,高水位线是oracle对表进行全表扫描的一个位置,(假如段分配了有10万个块,但是实际使用了2000个块,那么高水位线在2000个块的位置,那么如果你访问这个表的时候,oracle只访问2000个块,如果在10个块的位置,那么oracle访问表的时候会访问10万个块。)
通过delete对一个表删除,表的高水位线没有下来(假如有1w个块,当前如果高水位在1000,delete表后,高水位线还会在1000个块的位置)
需要对表进行空间整理
delete from t2;
commit;
analyze table t2 compute statistics;
select table_name,num_rows,blocks,empty_blocks,avg_space,chain_cnt,avg_row_len from user_tables where table_name = 'T2'
![](https://app.yinxiang.com/shard/s14/res/74581888-8b21-450a-a7fa-cb70fb7c672a.png?resizeSmall&width=786)
查询发现,数据是0行,但是还是占用265个块,那么oracle访问表的时候,会访问265个块。
set autotrace on;
select count(*) from t2;//查看执行计划
![](https://app.yinxiang.com/shard/s14/res/7808ca35-2f1a-4c9c-b2f2-cfa0abfb3da0.png?resizeSmall&width=786)
通过查询可以看到还是发生了269个读,也就是高水位没有释放
truncate table t2;
commit;
analyze table t2 compute statistics;
select table_name,num_rows,blocks,empty_blocks,avg_space,chain_cnt,avg_row_len from user_tables where table_name = 'T2'
![](https://app.yinxiang.com/shard/s14/res/6ff83d60-72e3-46e9-8573-eeee2bd457ac.png?resizeSmall&width=786)
查询看出,blocks已经清空,高水位降了
set autotrace on;
select count(*) from t2;//查看执行计划
![](https://app.yinxiang.com/shard/s14/res/708b7fab-bff5-4911-bc50-4a9c58d38ffd.png?resizeSmall&width=786)
发现读几乎没有了
oracle块的物理结构:
oracle块默认是8k
块头:块的物理地址,块属于哪个表空间,事务槽,行目录。
![](https://app.yinxiang.com/shard/s14/res/04d9774c-a42a-4a4f-a569-90e0380cdb8c.png?resizeSmall&width=786)
如图:块头从上往下用
数据行从下往上用
行的结构:
行的头部记录行的锁信息,第一列的长度,第一列值,第二列的长度,第二列的列值。。。所有的行都是连在一起的,首尾相连,没个行的长度都是不一样的
oracle读数据块的方式:
在块的头部有行目录,行目录里面将记录了每一行的起始位置。当oracle要找某一行的时候,会在行目录里面找到对应行的起始位置,然后到那个位置去,然后找对应的列,比如要找第三列,那么会先找到第一列的长度,然后跳过第一列的列值,接着找到第二列的长度,再跳过第二列值,就找到了第三列;如果把经常访问的列放在行头部,会有些许的优化,但是效果很小。
查询oracle默认数据块的大小:
show parameter block
![](https://app.yinxiang.com/shard/s14/res/cc97975c-66bc-43b8-a07d-b84769f3f0df.png?resizeSmall&width=786)
可以看到 db_block_size 是8k
查看操作系统的块大小:
dumpe2fs /dev/sda1
![](https://app.yinxiang.com/shard/s14/res/0e5b033d-320e-4115-b297-49b26914f5ac.png?resizeSmall&width=786)
block size是4k
也就是说2个操作系统的块是一个oracle的数据块
行连接和行迁移:pct_free
行连接:如果一行的数据太大了超过8k(block默认是8k),那么oracle会用多个块存储1行数据,第一个块指向第二个块,这就是行连接
行迁移:pct_free是一个块剩余空间,当oracle更新数据时原来更新后的数据长度过大,并达到块的pct_free时,这时这个行就不能放到这个块了,那么会启用新的块来放置更新的行,旧块里面的行不会指向新块里面的行。
查看一张表的行连接和行迁移状态:
select table_name,num_rows,blocks,empty_blocks,avg_space,chain_cnt,avg_row_len from user_tables where table_name = 'T2'
![](https://app.yinxiang.com/shard/s14/res/ec07e413-4b1c-4b15-913d-dc18ad15cb99.png?resizeSmall&width=786)
chain_cnt就是行连接和行迁移的数量,当avg_row_len大于块的大小时(8k或者查看参数),那么就是行连接,反之则是行迁移,
可以把表导出来再导进去,进行表整理.也可以对这张表建立16k或者32k的表空间.