SPLIT 分区的简单研究
1、split时需要有多少空闲空间
2、split会不会产生大量的redo
3、split的实现原理
我们要分两种情况讨论:
1、在split边界的两边都有值
2、只在split边界的一边有值
第一个问题:
1、在split边界的两边都有值
我们先创建一个只有20M的表空间,我们构造一个大小为11M的分区,看空间是否足够。
drop table s purge;
create table s(a char(1950),b date)
partition by range(b)
(partition p2008 values less than (to_date('2008-12-31','yyyy-mm-dd')) tablespace test
) pctfree 0;
--让两部分数据差别很大,更能说明问题
insert into s select 'a',sysdate-100 from dual connect by rownum<=1;
insert into s select 'a',sysdate from dual connect by rownum<=5500;
commit;
suk@D10R2N1> select round(sum(bytes))/1024/1024 "size(M)" from dba_segments where segment_name='S' and owner='SUK';
size(M)
----------
11
suk@D10R2N1> select sysdate from dual;
SYSDATE
-------------------
2008-10-17 02:01:04
suk@D10R2N1> ALTER TABLE S SPLIT partition p2008 AT (TO_DATE('2008-10-01','YYYY-MM-DD')) INTO (PARTITION p1 TABLESPACE TEST,PARTITION p2 TABLESPACE TEST) ;
ERROR at line 1:
ORA-01652: unable to extend temp segment by 128 in tablespace TEST
从这个例子可以看出,如果在split边界的两边都有值,则需要的空闲空间至少能放下被split的分区的数据。
2、只在split边界的一边有值
drop table s purge;
create table s(a char(1950),b date)
partition by range(b)
(partition p2008 values less than (to_date('2008-12-31','yyyy-mm-dd')) tablespace test
) pctfree 0;
--让范围都限制在当天
insert into s select 'a',trunc(sysdate) from dual connect by rownum<=9500;
commit;
suk@D10R2N1> select round(sum(bytes))/1024/1024 "size(M)" from dba_segments where segment_name='S' and owner='SUK';
size(M)
----------
19
suk@D10R2N1> ALTER TABLE S SPLIT partition p2008 AT (TO_DATE('2008-10-01','YYYY-MM-DD')) INTO (PARTITION p1 TABLESPACE TEST,PARTITION p2 TABLESPACE TEST) ;
Table altered.
这个例子说明,如果只在split边界的一边有值,则不需要额外的空间就可以split。
为什么区别这么大呢?ORACLE在内部是怎么做的?
我们仍然用两种方式做另外一个测试来验证:
1、在split边界的两边都有值
--创建表
drop table ex1 purge;
drop table ex2 purge;
drop table s purge;
suk@D10R2N1> create table s(a char(1950),b date)
2 partition by range(b)
3 (partition p2008 values less than (to_date('2008-12-31','yyyy-mm-dd')) tablespace test) pctfree 0;
Table created.
--记录redo size
suk@D10R2N1> select value from v$mystat where statistic#=134;
VALUE
----------
57820
suk@D10R2N1> insert into s select 'a',sysdate-mod(rownum,40) from dual connect by rownum<=4000;
4000 rows created.
suk@D10R2N1> select value from v$mystat where statistic#=134;
VALUE
----------
8471560
suk@D10R2N1> create table ex1 as select block_id,block_id+blocks-1 end_block from dba_extents where partition_name='P2008' and segment_name='S' order by extent_id;
Table created.
suk@D10R2N1> select value from v$mystat where statistic#=134;
VALUE
----------
8489680
suk@D10R2N1> ALTER TABLE S SPLIT partition p2008 AT (TO_DATE('2008-10-01','YYYY-MM-DD')) INTO (PARTITION P1 TABLESPACE test,PARTITION P2 TABLESPACE test) ;
Table altered.
suk@D10R2N1> select value from v$mystat where statistic#=134;
VALUE
----------
16931784
--从产生的redo看,spilt和第一步insert产生的redo量基本一致,故可以推断,split partition也是insert ....select....操作,当被split的分区的所有的数据insert到新分区后,删除旧分区。
suk@D10R2N1> create table ex2 as select block_id,block_id+blocks-1 end_block from dba_extents where partition_name in ('P1','P2') and segment_name='S' order by extent_id;
Table created.
--我们再从记录下来的extent信息看看使用情况:
suk@D10R2N1> set serverout on
suk@D10R2N1> DECLARE l_cnt INT:=0;
2 BEGIN
3 FOR c IN (SELECT * FROM ex2) LOOP
4 SELECT COUNT(1) INTO l_cnt FROM ex1 WHERE (c.block_id BETWEEN ex1.block_id AND ex1.end_block) OR (c.end_block BETWEEN ex1.block_id AND ex1.end_block);
5 IF l_cnt>0 THEN
6 dbms_output.put_line(c.block_id);
7 END IF;
8 END LOOP;
9 END;
10 /
PL/SQL procedure successfully completed.
这段程序的是为了找出S表在spilt前后被重用的block,没有结果输出,可以判定spilt后使用的空间都不在split前使用的空间范围内,这也说明了spilt时,所在表空间的空闲空间必须足够容纳被spilt的分区的所有数据。
2、只在split边界的一边有值
我们再看另外一种情况:只在split边界的一边有值
suk@D10R2N1> create table s(a char(1950),b date)
2 partition by range(b)
3 (partition p2008 values less than (to_date('2008-12-31','yyyy-mm-dd')) tablespace test) pctfree 0;
Table created.
suk@D10R2N1> select value from v$mystat where statistic#=134;
VALUE
----------
0
suk@D10R2N1> insert into s select 'a',sysdate-40 from dual connect by rownum<=4000;
4000 rows created.
suk@D10R2N1> select value from v$mystat where statistic#=134;
VALUE
----------
8413784
suk@D10R2N1> create table ex1 as select block_id,block_id+blocks-1 end_block from dba_extents where partition_name='P2008' and segment_name='S' order by extent_id;
Table created.
suk@D10R2N1> select value from v$mystat where statistic#=134;
VALUE
----------
8431020
suk@D10R2N1> ALTER TABLE S SPLIT partition p2008 AT (TO_DATE('2008-10-01','YYYY-MM-DD')) INTO (PARTITION P1 TABLESPACE test,PARTITION P2 TABLESPACE test) ;
Table altered.
suk@D10R2N1> select value from v$mystat where statistic#=134;
VALUE
----------
8515144
首先我们可以看出,这种情况下,split产生的redo非常少,我们可以推测这种情况下,数据没有做实际的移动,只是简单修改数据字典的信息。为了验证这一点,我们看看spilt前后extent信息:
suk@D10R2N1> select block_id,end_block from ex1
2 minus
3 select block_id,end_block from ex2;
no rows selected
suk@D10R2N1> select block_id,end_block from ex2
2 minus
3 select block_id,end_block from ex1;
BLOCK_ID END_BLOCK
---------- ----------
1033 1040
suk@D10R2N1> select segment_name,partition_name from dba_extents where block_id=1033 and blocks=1040-1033+1 and owner='SUK';
SEGMENT_NAME PARTITION_NAME
------------------------------ ------------------------------
S P2
这个结果表明:对于P1,它使用的block和split前是完全一致的;而仅仅是为P2单独分配一个初始化的extent。这也证明了只在split边界的一边有值的情况下,数据没有发生实际移动,仅仅修改一些数据字典信息。
但是这种情况也有特例:就算只在split边界的一边有值,如果有值的一端在split后对应的分区前后表空间不一致,,则新的表空间的空闲空间至少能放下被split的分区的数据。
如果有兴趣,可以用trace跟踪一下,我们可以发现split时,会递归调用如下SQL:
select /*+ FIRST_ROWS PARALLEL("S", 1) */ 1
from
"SUK"."S" PARTITION ("P2008") where ( ( ( ( "B" < TO_DATE(' 2008-10-01
00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') ) ) ) )
and rownum < 2
select /*+ FIRST_ROWS PARALLEL("S", 1) */ 1
from
"SUK"."S" PARTITION ("P2008") where ( ( ( ( "B" >= TO_DATE(' 2008-10-01
00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN') ) ) ) )
and rownum < 2
这两个SQL就是用于判断在split边界的两边是否有值。在这里,oracle是非常聪明的,它根据这个判断结果来决定是否有必要移动数据,在某些情况下可以节省很多资源。
到这里,我们可以回答开头提出的几个问题了:
1、split时需要有多少空闲空间
如果在split边界的两边都有值,则需要的空闲空间必能能够放下被split分区的所有数据。
只在split边界的一边有值,且split后有值的一端对应的表空间与原分区对应表空间不一致,则需要的空闲空间必能能够放下被split分区的所有数据。
只在split边界的一边有值,且split后有值的一端对应的表空间与原分区对应表空间一致,则无需额外的空间。
2、split会不会产生大量的redo
split做的实际上是insert...select...操作,所以产生的日志量与是否有数据移动有关。
如果在split边界的两边都有值,则有数据移动,会为移动的数据产生redo。
只在split边界的一边有值,且split后有值的一端对应的表空间与原分区对应表空间不一致,则有数据移动,会为移动的数据产生redo。
只在split边界的一边有值,且split后有值的一端对应的表空间与原分区对应表空间一致,则无数据移动,不会为数据产生redo。
3、split的实现原理
split时,首先判断在split的边界是否都有数据存在。
如果在split边界的两边都有值,则产生两个新的分区,把原分区的所有数据insert到新分区后,删除原分区,更新数据字典。
只在split边界的一边有值,且split后有值的一端对应的表空间与原分区对应表空间不一致,则产生两个新的分区,把原分区的所有数据insert到新分区后,删除原分区,更新数据字典。
只在split边界的一边有值,且split后有值的一端对应的表空间与原分区对应表空间一致,则新加一个分区,并修改原分区信息为另一个新分区的信息,无数据移动。
SPLIT 分区的简单研究相关推荐
- oracle分区区别,oracle范围分区表和INTERVAL分区表对于SPLIT分区的区别
范围分区表和INTERVAL分区表是可以相互转化的,不过二者还是有所区别的.比如在SPLIT分区的时候,范围分区表没有限制,而INTERVAL分区表则可能报错. 首先看范围分区的例子: SQL> ...
- 简单研究用于监控数通设备的Zabbix模板:Template Module Interfaces SNMP与Template Module EtherLike-MIB SNMP
本人的工作环境中已经有一套Zabbix平台用于监控1000台数量以上的交换机,该运维平台主要有如下作用: 查找某个区域的某台设备IP地址以方便管理员远程登录.查看/修改设备配置: 通过SNMP检测设备 ...
- [转载]3721驻留机制简单研究
[转载]3721的驻留机制简单研究 Quaful@水木清华 简单研究了一下3721的机制,写在这里,作为心得笔记吧.大部分收获都来自 Softice + 反汇编,不一定适用于某些版本. 1. CnsM ...
- win10使用磁盘管理器创建并配置VHD虚拟磁盘,创建分区和简单卷以及虚拟磁盘的挂载和分离
(一)实验目的 通过本实验,了解微软虚拟磁盘的使用,掌握Windows磁盘管理器创建微软虚拟磁盘的方法,熟悉VHD虚拟磁盘的基本配置以及VHD虚拟磁盘的挂载和分离操作. (二) 实验环境 1台装有Wi ...
- 泰山OFFICE技术讲座:竖排时中文标点的简单研究
中文标点有两类,横排和竖排.那么,在竖排时,会产生什么差异呢?是否会因为竖排标点,产生布局的差异?于是进行了简单研究: 横排时,竖排标点,作为普通字符对待,没有特殊处理. 竖排时,竖排标点还是作为普通 ...
- 服务器如何删除所有磁盘信息,关于怎样删除EFI分区,简单省事,很多换下来的硬盘都有这个分区...
前言,很多人升级了硬盘,凡是安装过MAC OS X系统硬盘会留下了一个200MB的EFI系统分区, 在Windows磁盘管理下显示为EFI保护分区,无法正常删除或格式化操作. 我试过很多软件删除这个分 ...
- OpenGL的简单研究-开端
一直想要学习的但是没有学习的东西,大学一直在等待这个时间,终于可以闲下来研究一下这个部分的内容了. 计算机图形学,让计算机处理各种图像的东西,里面也存在很多算法和数学知识,很值得研究的一个领域,之前一 ...
- mysql分区方案的研究
笔者觉得,分库分表确实好的.但是,动不动搞分库分表,太麻烦了.分库分表虽然是提高数据库性能的常规办法,但是太麻烦了.所以,尝试研究mysql的分区到底如何. 之前写过一篇文章,http://www.c ...
- 对List.Sort的简单研究
最近一直忙着修改项目中的bug,特别是一些绑定的列表排序,因为是中途加入的,所以我一般不改变别人的存储过程或者类方法,只在需要的时候帮其排序一下,不过非常郁闷...... 为什么呢???存储过程用得是 ...
最新文章
- The Pediatric Cancer Genome Project 儿童癌症基因组计划
- PostgreSQL-数据复制
- python封装c++_用pybind11封装C++实现的函数库
- java客户端访问kafka
- ACM-ICPC 2019 山东省省赛 A Calandar
- 敏捷制造:并不是你想像的矛盾体
- React开发(112):不要写多余的select
- html网页 table布局实例,HTML用Table表格对网页布局
- matlab实现双边滤波_【他山之石】pytorch 实现双边滤波
- Django编写RESTful API(二):请求和响应
- linux查询匹配个数,查找与linux中目录中的模式匹配的文件数
- 云计算的SPI服务模型
- C语言实现万年历(附代码)
- 【git】 vim的使用
- 【自动化__GUI自动化】__java__模拟功能操作__鼠标
- Docker新手入门基础知识与实战教程
- 大一想去参加培训的学生
- java格林尼治时间_Java日期时间使用总结
- walking机器人入门教程-rviz插件-多点导航插件的航点保存和加载
- MongoDB 分片迁移