Replica small data to PostgreSQL from Oracle's Big table
生活随笔
收集整理的這篇文章主要介紹了
Replica small data to PostgreSQL from Oracle's Big table
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
有時候會遇到從Oracle同步數據到PostgreSQL數據庫的需求, 當Oracle那邊的表是大表的時候,? 即使同步到PostgreSQL的數據量很小也可能很慢. 原因可能是 1. Oracle那邊的執行計劃可能不優. 比如走全表掃描了. 或者走的索引不對.?
2. 條件沒有正確的轉換給Oracle, 那就慘了, 數據全部取過來然后在PostgreSQL中過濾.
例如我們需要同步的是前一天的數據, 實際上走分區的全表掃描可能比走索引快. 但是又不好寫HINT. 那么怎么來解決這種問題呢? 來看個例子 :? 例如我們要從Oracle的tbl表同步前一天的數據, 這個表做了按月分區. ?一個月大概5000W記錄. 10GB左右. 我們要同步的數據條件是cond1 = '1' and cond2 in( '10','15'). 這個取出來每天只有幾百條記錄.? 同步的SQL應該是 select a, b, c, createtime from tbl where createtime>=sysdate-1 and createtime<sysdate and?cond1 = '1' and cond2 in( '10','15'). 這個SQL可以走時間索引也可以走cond1和cond2的聯合索引. 或者走分區掃描. 幾種執行計劃的時間相差比較大.? 走聯合索引的效率可能是最高的, 不過這個索引不存在, 在ORACLE中也不存在PostgreSQL中這樣的partial索引, 而且建立索引之后會帶來寫入的延遲. 最終決定不建立.
為了避免第二種情況的發生, 讓PG讀ORACLE的視圖, 而不是直接讀表. 通過限定視圖中的數據量來限定PG的最大可能獲取量.
oracle :? digoal user :
create view v_tbl as select a,b,c,createtime from tbl where cond1 = '1' and cond2 in( '10','15') and createtime >= sysdate-7;
這里限定我們要限定的條件, 并且加了一個時間的限定. 然后再到PostgreSQL中創建基于這個視圖的外部表. 注 : 如果你的oracle_fdw支持where語句下發的話, 可以不用這么麻煩.
postgresql9.1 :? superuser :
cretae role digoal nosuperuser encrypted password 'DIGOAL'; create server digoal foreign data wrapper oracle_fdw options (dbserver '//192.168.xxx.xxx:1521/digoal'); create user mapping for digoal server digoal options (user 'digoal',password 'digoal_oracle');create FOREIGN table digoal.ora_tbl (a varchar(9),b varchar(420),c varchar(45),createtime timestamp(0) without time zone) server digoal options (table 'v_tbl',schema 'digoal',plan_costs 'true');grant select on digoal.ora_tbl to digoal;
digoal user :?
create table tbl (a varchar(9),b varchar(420),c varchar(45),createtime timestamp(0) without time zone); create table sync_record(modifytime timestamp(0) without time zone);
sync_record 用于記錄最后一次同步時間, 防止重復同步. 下面是同步調用的函數 :
create or replace function sync_tbl() returns text as $$ declare v_modifytime timestamp(0) without time zone; v_now timestamp(0) without time zone; begin v_now = now(); -- lock表防止同時調用這個同步過程. 導致重復同步 lock table sync_record in exclusive mode; perform 1 from sync_record limit 1; if not found then insert into sync_record(modifytime) values(v_now-interval '1 day'); end if; select modifytime into v_modifytime from sync_record limit 1; if v_modifytime < current_date then insert into tbl(a,b,c,createtime) select a,b,c,createtime from ora_tbl where createtime >=date(v_modifytime) and createtime < date(v_now); update sync_record set modifytime=v_now; end if; return 'ok'; exception when others then return 'error'; end; $$ language plpgsql;
digoal=> select * from sync_tbl();sync_tbl_app_charge ---------------------ok (1 row)
2. 條件沒有正確的轉換給Oracle, 那就慘了, 數據全部取過來然后在PostgreSQL中過濾.
例如我們需要同步的是前一天的數據, 實際上走分區的全表掃描可能比走索引快. 但是又不好寫HINT. 那么怎么來解決這種問題呢? 來看個例子 :? 例如我們要從Oracle的tbl表同步前一天的數據, 這個表做了按月分區. ?一個月大概5000W記錄. 10GB左右. 我們要同步的數據條件是cond1 = '1' and cond2 in( '10','15'). 這個取出來每天只有幾百條記錄.? 同步的SQL應該是 select a, b, c, createtime from tbl where createtime>=sysdate-1 and createtime<sysdate and?cond1 = '1' and cond2 in( '10','15'). 這個SQL可以走時間索引也可以走cond1和cond2的聯合索引. 或者走分區掃描. 幾種執行計劃的時間相差比較大.? 走聯合索引的效率可能是最高的, 不過這個索引不存在, 在ORACLE中也不存在PostgreSQL中這樣的partial索引, 而且建立索引之后會帶來寫入的延遲. 最終決定不建立.
為了避免第二種情況的發生, 讓PG讀ORACLE的視圖, 而不是直接讀表. 通過限定視圖中的數據量來限定PG的最大可能獲取量.
oracle :? digoal user :
create view v_tbl as select a,b,c,createtime from tbl where cond1 = '1' and cond2 in( '10','15') and createtime >= sysdate-7;
這里限定我們要限定的條件, 并且加了一個時間的限定. 然后再到PostgreSQL中創建基于這個視圖的外部表. 注 : 如果你的oracle_fdw支持where語句下發的話, 可以不用這么麻煩.
postgresql9.1 :? superuser :
cretae role digoal nosuperuser encrypted password 'DIGOAL'; create server digoal foreign data wrapper oracle_fdw options (dbserver '//192.168.xxx.xxx:1521/digoal'); create user mapping for digoal server digoal options (user 'digoal',password 'digoal_oracle');create FOREIGN table digoal.ora_tbl (a varchar(9),b varchar(420),c varchar(45),createtime timestamp(0) without time zone) server digoal options (table 'v_tbl',schema 'digoal',plan_costs 'true');grant select on digoal.ora_tbl to digoal;
digoal user :?
create table tbl (a varchar(9),b varchar(420),c varchar(45),createtime timestamp(0) without time zone); create table sync_record(modifytime timestamp(0) without time zone);
sync_record 用于記錄最后一次同步時間, 防止重復同步. 下面是同步調用的函數 :
create or replace function sync_tbl() returns text as $$ declare v_modifytime timestamp(0) without time zone; v_now timestamp(0) without time zone; begin v_now = now(); -- lock表防止同時調用這個同步過程. 導致重復同步 lock table sync_record in exclusive mode; perform 1 from sync_record limit 1; if not found then insert into sync_record(modifytime) values(v_now-interval '1 day'); end if; select modifytime into v_modifytime from sync_record limit 1; if v_modifytime < current_date then insert into tbl(a,b,c,createtime) select a,b,c,createtime from ora_tbl where createtime >=date(v_modifytime) and createtime < date(v_now); update sync_record set modifytime=v_now; end if; return 'ok'; exception when others then return 'error'; end; $$ language plpgsql;
digoal=> select * from sync_tbl();sync_tbl_app_charge ---------------------ok (1 row)
總結
以上是生活随笔為你收集整理的Replica small data to PostgreSQL from Oracle's Big table的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql一些操作个人备忘(持续更新)
- 下一篇: mysql在没有任何用户的情况下,如何恢