最近有个小模块,是在灾备机之间拷贝备份数据,同时把相关的数据表也拷贝到目标系统上。
这里涉及到一个问题:Oracle表空间达到上限之后怎么处理?
一般来说,将表空间设置为自增,不限制最大容量可以满足大部分需求。但是,即便是表空间不设置上限,数据文件的大小也是会有最大值的,这是因为Oracle 数据文件最多可以包含 4194303 个 Oracle 数据块,通常数据块大小为8KB,也就是说,文件尺寸的最大值一般是32GB。
表空间达到这个理论上的容量上限之后,最好的处理办法应该是追加数据文件吧,语句如下:
ALTER TABLESPACE DATA_TEST_TS ADD DATAFILE 'D:\..\YOUR_DATA_FILE_PATH.dbf' SIZE 50m AUTOEXTEND ON NEXT 50M MAXSIZE 32767m
如何快速生成大量的测试数据呢?比如需要1TB的测试数据,该怎么处理?
我觉得按下面的步骤会稍微快一些:
1.创建表并循环插入数据,使得这张表大概占用1GB的空间。
2.exp命令导出表结构和数据。
3.imp命令重复多次导入第二步的***.dmp文件。
在第三步之前可以先将原表重命名,避免表名冲突。不知道向原表追加导入是不是可行,也不知道会不会使导入时间变长,没有尝试过。。。
具体实现是这样的:
先创建表空间并追加N个数据文件,随后创建一张大小1GB左右的表(这个时间比较长),然后导出这个表,最后用一个循环修改原表名并导入。导入1GB的数据要比使用create...insert快得多。
创建表空间和创建表的sql如下:
DECLARE
-- 数据文件路径(需修改)
DataFilePath varchar2(1024) := 'D:\app\Administrator\oradata\orcl\';
-- 表空间数据文件个数
DataFileNum number := 33;
-- 每个表的行数
TableRowNum number := 400000;
-- sql
v_sql varchar2(1024);
-- FOR
CNT number;
BEGIN
----------------------------------------------
----------------------------------------------
-------------1.创建表空间---------------------
----------------------------------------------
----------------------------------------------
EXECUTE IMMEDIATE 'drop tablespace DATA_TEST_TS including contents and datafiles';
EXCEPTION WHEN OTHERS THEN NULL;
-- 创建表空间
v_sql := 'create tablespace DATA_TEST_TS logging datafile ''' || DataFilePath || 'DATA_TEST_TS1.dbf'
|| ''' size 50m autoextend on next 50m maxsize 32767m extent management local';
EXECUTE IMMEDIATE v_sql;
dbms_output.put_line(v_sql);
-- 表空间追加数据文件:
CNT := 2;
WHILE CNT < DataFileNum LOOP
v_sql := 'ALTER TABLESPACE DATA_TEST_TS ADD DATAFILE ''' || DataFilePath || 'DATA_TEST_TS' || CNT || '.dbf'
|| ''' SIZE 50m AUTOEXTEND ON NEXT 50M MAXSIZE 32767m';
CNT := CNT+1;
BEGIN
EXECUTE IMMEDIATE v_sql;
dbms_output.put_line(v_sql);
END;
END LOOP;
----------------------------------------------
----------------------------------------------
-------------2.建表插数据---------------------
----------------------------------------------
----------------------------------------------
-- 建表并插数据
v_sql := 'create table TestTable01 tablespace DATA_TEST_TS as select rownum as id,'
|| 'to_char(sysdate + rownum/24/3600, ''yyyy-mm-dd hh24:mi:ss'') as inc_datetime,'
||'trunc(dbms_random.value(0, 1000000)) as random_id,'
||'dbms_random.string(''x'', 2000) as random_string '
||'from dual connect by level <= '||TableRowNum;
EXECUTE IMMEDIATE v_sql;
dbms_output.put_line(v_sql);
END;
/
EXIT;
上面SQL里面的数据文件个数和表的行数按自己的需要进行修改,因为这表的每条记录大概是2KB,我插了40万行。
再后来,又写了一个重命名表的sql文件:
DECLARE
-- 表名
TableName varchar2(1024);
-- sql
v_sql varchar2(200);
BEGIN
SELECT to_char((SYSDATE - TO_DATE('1970-1-1 8', 'YYYY-MM-DD HH24')) * 86400) as TIMESTAMP INTO TableName FROM DUAL;
TableName := 'TestTable'||TableName;
dbms_output.put_line(TableName);
v_sql := 'ALTER TABLE TestTable01 RENAME TO '||TableName;
dbms_output.put_line(v_sql);
EXECUTE IMMEDIATE v_sql;
END;
/
EXIT;
为啥非要写成两个***.sql呢,因为exp和imp命令需要在cmd里执行,我想把整个过程写成一个***.bat,让它自己跑去吧。最后就是那个.bat了,里面的用户名和密码和数据库名换一下就好了:
@echo off
::--1.生成数据
::Oracle用户需有DBA权限
echo "--->Generate Test Data ...";
sqlplus username/pwd@DATABASE @D:\generate.sql
echo "--->Generate Test Data Finish";
::--2.导出数据
echo "--->Export Test Data ...";
exp username/pwd@DATABASE file=d:\daochu.dmp tables=(TestTable01);
echo "--->Export Test Data Finish";
::导入次数(按需修改)
set Num=800
set Cnt=0
::--3.循环导入
:Loop
echo "--->Rename Original Table ...";
sqlplus username/pwd@DATABASE @D:\rename.sql
echo "--->Import Test Data ...";
imp username/pwd@DATABASE file=d:\daochu.dmp tables=(TestTable01);
echo "--->Import Test Data Finish";
set /a Cnt=%Cnt%+1
if "%Cnt%"=="%Num%" goto ExitEnd
goto Loop
:ExitEnd
echo "--->Rename Original Table ...";
sqlplus username/pwd@DATABASE @D:\rename.sql
echo "--->FINISH";
pause