1. 程式人生 > >Oracle快速生成大量測試資料

Oracle快速生成大量測試資料

最近有個小模組,是在災備機之間拷貝備份資料,同時把相關的資料表也拷貝到目標系統上。

這裡涉及到一個問題: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/[email protected] @D:\generate.sql
echo "--->Generate Test Data Finish";

::--2.匯出資料

echo "--->Export Test Data ...";
exp username/[email protected] 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/[email protected] @D:\rename.sql

echo "--->Import Test Data ...";
imp username/[email protected] 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/[email protected] @D:\rename.sql


echo "--->FINISH";

pause