Oracle 分区拆分期间何时移动数据?

Sql*_*yan 2 oracle partitioning

我需要拆分一个 Oracle 分区,我对执行拆分时 Oracle 是否要物理重新定位数据感到困惑。这是我打算做的:

alter table SCHEMA.DATATABLE
   split partition MAXVAL_PART
   at (TO_DATE(' 2013-04-01 00:00:00',
               'SYYYY-MM-DD HH24:MI:SS',
               'NLS_CALENDAR=GREGORIAN'))
   into (partition PARTFOREXISTINGROWS
        tablespace EXISTINGMAXVALTABLESPACE,
         partition MAXVAL_PART
        tablespace NEWMAXVALTABLESPACE);
Run Code Online (Sandbox Code Playgroud)

问题是我当前的 MAXVAL_PART 中有 320 GB 的数据,我不想在磁盘上物理移动这些数据。如果我在 2013 年 4 月 1 日切断分区,那么新分区中将没有数据,但是我收到了关于这是否仍然需要移动所有数据的相互矛盾的信息。理想情况下,Oracle 看到我的新 MAXVAL 分区将为空,在新表空间中定义它,然后我就完成了。

此命令会移动磁盘上已有的数据,还是将其留在原处并创建一个新分区?

这篇文章说 Oracle 会检测空分区并进行快速拆分 http://docs.oracle.com/cd/B19306_01/server.102/b14231/partiti.htm

但是我在很多地方看到拆分意味着所有数据都被移动到新的存储中。是哪个?

Phi*_*lᵀᴹ 5

它不会移动数据。

测试用例:

SQL> CREATE TABLESPACE myts1 DATAFILE '/u01/app/oracle/oradata/ORA112/myts1_01.dbf' size 50M;

Tablespace created.

SQL> CREATE TABLESPACE mytsmax DATAFILE '/u01/app/oracle/oradata/ORA112/mytsmax_01.dbf' size 50M;

Tablespace created.

SQL> CREATE TABLE mytable (id NUMBER, dt DATE)
PARTITION BY RANGE (dt)
  (PARTITION mytablep1 VALUES LESS THAN (TO_DATE('2013-01-01', 'YYYY-MM-DD')) TABLESPACE myts1,
   PARTITION mytablep2 VALUES LESS THAN (TO_DATE('2013-02-01', 'YYYY-MM-DD')) TABLESPACE myts1,
   PARTITION mytablep3 VALUES LESS THAN (TO_DATE('2013-03-01', 'YYYY-MM-DD')) TABLESPACE myts1,
   PARTITION mytablep4 VALUES LESS THAN (MAXVALUE) TABLESPACE myts1
  );  

Table created.
Run Code Online (Sandbox Code Playgroud)

我插入了一些数据。结果:

SQL> select dt, count(*) 
  2  from mytable
  3  group by dt;

DT      COUNT(*)
--------- ----------
11-NOV-12     262272
11-JAN-13     262272
11-FEB-13     262272
11-MAR-13     262272
Run Code Online (Sandbox Code Playgroud)

现在,确定行是否移动的最佳方法是查看其rowid. 在rowid对于给定的行是根据该行的一个数据文件和块的位置。因此,如果rowid发生变化,则意味着该行已移动!文档链接

因此,创建一个表来保存表中现有行的 rowids,并插入它们:

SQL> create table myrowids ( r rowid );

Table created.

SQL> insert into myrowids ( select rowid from mytable );

1049088 rows created.

SQL> commit;
Run Code Online (Sandbox Code Playgroud)

执行拆分:

SQL> ALTER TABLE mytable
SPLIT PARTITION mytablep4
AT ( TO_DATE('2013-04-01', 'YYYY-MM-DD') )
INTO ( PARTITION mytablep4 TABLESPACE myts1, PARTITION mytablep5 TABLESPACE mytsmax );   

Table altered.

SQL>
Run Code Online (Sandbox Code Playgroud)

检查行没有移动(可以使用 anEXISTS代替):

SQL> select count(*) from myrowids where r not in ( select rowid from mytable );

  COUNT(*)
----------
     0

SQL>
Run Code Online (Sandbox Code Playgroud)

他们没有!