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 分区的简单研究相关推荐

  1. oracle分区区别,oracle范围分区表和INTERVAL分区表对于SPLIT分区的区别

    范围分区表和INTERVAL分区表是可以相互转化的,不过二者还是有所区别的.比如在SPLIT分区的时候,范围分区表没有限制,而INTERVAL分区表则可能报错. 首先看范围分区的例子: SQL> ...

  2. 简单研究用于监控数通设备的Zabbix模板:Template Module Interfaces SNMP与Template Module EtherLike-MIB SNMP

    本人的工作环境中已经有一套Zabbix平台用于监控1000台数量以上的交换机,该运维平台主要有如下作用: 查找某个区域的某台设备IP地址以方便管理员远程登录.查看/修改设备配置: 通过SNMP检测设备 ...

  3. [转载]3721驻留机制简单研究

    [转载]3721的驻留机制简单研究 Quaful@水木清华 简单研究了一下3721的机制,写在这里,作为心得笔记吧.大部分收获都来自 Softice + 反汇编,不一定适用于某些版本. 1. CnsM ...

  4. win10使用磁盘管理器创建并配置VHD虚拟磁盘,创建分区和简单卷以及虚拟磁盘的挂载和分离

    (一)实验目的 通过本实验,了解微软虚拟磁盘的使用,掌握Windows磁盘管理器创建微软虚拟磁盘的方法,熟悉VHD虚拟磁盘的基本配置以及VHD虚拟磁盘的挂载和分离操作. (二) 实验环境 1台装有Wi ...

  5. 泰山OFFICE技术讲座:竖排时中文标点的简单研究

    中文标点有两类,横排和竖排.那么,在竖排时,会产生什么差异呢?是否会因为竖排标点,产生布局的差异?于是进行了简单研究: 横排时,竖排标点,作为普通字符对待,没有特殊处理. 竖排时,竖排标点还是作为普通 ...

  6. 服务器如何删除所有磁盘信息,关于怎样删除EFI分区,简单省事,很多换下来的硬盘都有这个分区...

    前言,很多人升级了硬盘,凡是安装过MAC OS X系统硬盘会留下了一个200MB的EFI系统分区, 在Windows磁盘管理下显示为EFI保护分区,无法正常删除或格式化操作. 我试过很多软件删除这个分 ...

  7. OpenGL的简单研究-开端

    一直想要学习的但是没有学习的东西,大学一直在等待这个时间,终于可以闲下来研究一下这个部分的内容了. 计算机图形学,让计算机处理各种图像的东西,里面也存在很多算法和数学知识,很值得研究的一个领域,之前一 ...

  8. mysql分区方案的研究

    笔者觉得,分库分表确实好的.但是,动不动搞分库分表,太麻烦了.分库分表虽然是提高数据库性能的常规办法,但是太麻烦了.所以,尝试研究mysql的分区到底如何. 之前写过一篇文章,http://www.c ...

  9. 对List.Sort的简单研究

    最近一直忙着修改项目中的bug,特别是一些绑定的列表排序,因为是中途加入的,所以我一般不改变别人的存储过程或者类方法,只在需要的时候帮其排序一下,不过非常郁闷...... 为什么呢???存储过程用得是 ...

最新文章

  1. The Pediatric Cancer Genome Project   儿童癌症基因组计划
  2. PostgreSQL-数据复制
  3. python封装c++_用pybind11封装C++实现的函数库
  4. java客户端访问kafka
  5. ACM-ICPC 2019 山东省省赛 A Calandar
  6. 敏捷制造:并不是你想像的矛盾体
  7. React开发(112):不要写多余的select
  8. html网页 table布局实例,HTML用Table表格对网页布局
  9. matlab实现双边滤波_【他山之石】pytorch 实现双边滤波
  10. Django编写RESTful API(二):请求和响应
  11. linux查询匹配个数,查找与linux中目录中的模式匹配的文件数
  12. 云计算的SPI服务模型
  13. C语言实现万年历(附代码)
  14. 【git】 vim的使用
  15. 【自动化__GUI自动化】__java__模拟功能操作__鼠标
  16. Docker新手入门基础知识与实战教程
  17. 大一想去参加培训的学生
  18. java格林尼治时间_Java日期时间使用总结
  19. walking机器人入门教程-rviz插件-多点导航插件的航点保存和加载
  20. MongoDB 分片迁移

热门文章

  1. 数据结构线性表博客作业总结
  2. Tensorflow中2D卷积API使用
  3. Django入门实战【3步曲】
  4. MySql 数据操作类
  5. 经常使用Log日志打印输出
  6. ios开发 json数据文件的存取
  7. ArcGIS Desktop开发基础(转)
  8. s6-7 TCP 传输策略
  9. gitee最多上传多大文件_H5移动端图片压缩上传,基于Jquery的前端,实现拍照上传,选择相册
  10. python简笔画绘制 数据驱动绘图_python:绘制枫叶简笔画