在異構資料庫環境下,往往需要將 Oracle 資料庫的結構定義(Schema)遷移至其他平台,而不帶入龐大的業務數據。這類「僅遷移中繼資料」的需求常見於開發/測試環境建置、架構審查、或是異構資料庫同步初始化等場景。本文將詳細說明如何使用 Data Pump(expdp/impdp)搭配 METADATA_ONLY 參數,達成結構遷移的目標,並針對遷移後常見的空間浪費問題提供解決方案。
使用 expdp 工具,指定 CONTENT=METADATA_ONLY 參數,僅匯出物件定義(表、索引、視圖、序列、PL/SQL 等),不包含任何資料列。
expdp system/sywg1234 directory=test dumpfile=test.dump logfile=test.log \
schemas=SYWG,GAZX,WEBCALL,HQ,SJCK,SJPZ CONTENT=METADATA_ONLY
關鍵參數說明:
schemas:指定要遷移的 Schema 列表,可一次包含多個業務 Schema。CONTENT=METADATA_ONLY:核心參數,確保僅匯出 DDL 定義。由於目標平台的儲存路徑、檔案大小規格通常與來源不同,建議使用 TOAD 或 SQL 查詢 DBA_TABLESPACES/DBA_DATA_FILES 產生建立表空間的 DDL 腳本,然後手動調整:
將 .dump 檔案複製至目標資料庫伺服器的 Directory 物件對應目錄下,建立同名 Directory 物件,然後執行 impdp:
impdp system/sywg1234 directory=test dumpfile=test.dump logfile=test_imp.log \
CONTENT=METADATA_ONLY exclude=statistics
注意事項:
exclude=statistics:避免匯入過時的統計資訊,後續會重新收集。VERSION=12(視來源版本而定)確保相容性。僅匯入結構卻發現表段佔用驚人空間?這通常是因為來源表曾經歷大量資料寫入/刪除,導致 High Water Mark (HWM) 極高,匯入時 INITIAL/NEXT 儲存參數被保留,導致空表一出生就分配大量 Extent。
匯入完成後,先為所有業務表產生並執行統計收集腳本:
SELECT 'EXEC DBMS_STATS.GATHER_TABLE_STATS('''||owner||''','''||table_name||''');'
FROM all_tables
WHERE owner IN ('GAZX','SJCK','SJPZ','SYWG','HQ','WEBCALL');
建議使用 DBMS_STATS 套件而非舊式 ANALYZE,前者支援並行、採樣率控制、直方圖等進階功能。
查詢佔用空間前幾大的表段:
SELECT owner, segment_name, segment_type, bytes/1024/1024 AS mb
FROM dba_segments
WHERE owner = 'GAZX' AND segment_type = 'TABLE'
ORDER BY 4 DESC;
確認表確無資料(SELECT COUNT(*) FROM owner.table),再檢查是否啟用 Row Movement:
SELECT row_movement FROM all_tables WHERE owner='GAZX' AND table_name='GSGG';
若為 DISABLED,需先啟用:
ALTER TABLE GAZX.GSGG ENABLE ROW MOVEMENT;
批次產生啟用腳本:
SELECT 'ALTER TABLE '||owner||'.'||segment_name||' ENABLE ROW MOVEMENT;'
FROM dba_segments
WHERE owner='GAZX' AND segment_type='TABLE';
ALTER TABLE GAZX.GSGG SHRINK SPACE CASCADE;
CASCADE 會同步壓縮關聯索引。批次腳本:
SELECT 'ALTER TABLE '||owner||'.'||segment_name||' SHRINK SPACE CASCADE;'
FROM dba_segments
WHERE owner='GAZX' AND segment_type='TABLE';
表段壓縮完成後,可嘗試 ALTER DATABASE DATAFILE '...' RESIZE ... 將釋放的空間歸還給作業系統。
核對來源/目標端物件數量一致性:
-- 表數量
SELECT owner, COUNT(*) FROM all_tables
WHERE owner IN ('GAZX','SJCK','SJPZ','SYWG','HQ','WEBCALL')
GROUP BY owner;
-- 索引數量
SELECT owner, COUNT(*) FROM all_indexes
WHERE owner IN ('GAZX','SJCK','SJPZ','SYWG','HQ','WEBCALL')
GROUP BY owner;
若數量不符,檢查 impdp log 中的 ORA-39083/ORA-00955 等錯誤,針對性處理。
掌握上述流程,即可在異構、跨版本、跨平台場景下,輕量、可控地完成 Oracle 結構遷移,為後續數據同步或應用測試奠定堅實基礎。