簡體   English   中英

在 Hana DB 中傳輸 4 個虛擬 SDA 表的最佳方式

[英]Optimal way to transfer 4 Virtual SDA Tables in Hana DB

問題:我的團隊目前正在進行從 ECC 系統到新 S/4 Hana 系統的 ERP 遷移。 作為上線的一部分,我們的團隊需要將所有表從 S/4 系統復制到我們將托管數據的 SLT 模式中。 大多數表將由 SAP 之外的 SLT 復制處理。 但是,由於時間緊迫,我們確定了 4 個需要多天復制的表。 想法是從遠程源 (ABAP/SDA) 復制現有數據並放置在我們的 SLT 模式中。 一旦完成,我們可以激活點前向復制並允許更新所有新的或修改的記錄查看 SLT 復制。

嘗試的方法:我們當前的方法是與后端 S/4 數據庫建立 SDA 連接,並按年份分解數據,以使用存儲過程插入到我們的本地表中。 這種方法出現了許多問題,但它目前正在發揮作用。 它只是超級慢。

論壇問題:

  • 這是您處理此類問題的方式嗎? 如果沒有,您提出的解決方案是什么?
  • 您是否在目標表中看到任何需要自定義以提高性能的內容?
  • 存儲過程中是否有任何突出的地方需要調整?

示例:假設我們有一個名為: A_tbl的源表

  • A_tbl 中有 5 億條記錄
  • 大約 500 列寬

然后我們將有我們的目標表: B_tbl

  • 與 A_tbl (500) 相同的列數
  • 12 人輪循分區
  • 索引 5 列

當前程序:

CREATE OR REPLACE procedure LOAD_B_TBL_FROM_A_TBL ()
as
begin

    declare v_offset_nbr integer;
    declare v_record_count integer;
    declare v_commit_count integer;
    declare i integer;
    declare v_year nvarchar(4);
    declare v_record_per_commit_count CONSTANT INT = 1000000; 
    declare v_table_name CONSTANT NVARCHAR(30) = 'A_TBL';   
    declare v_start_year CONSTANT INT = 2011;
    declare v_end_year CONSTANT INT = 2022;
    declare year_nbr integer;

    
    for year_nbr in v_start_year..v_end_year do
    
        select IfNull(max(offset_nbr),0) into v_offset_nbr from B_TBL_SCHEMA.bulk_load_log where table_name = :v_table_name AND year_nbr = to_varchar(year_nbr); -- Get offset number of records
        
        select count(*) into v_record_count from A_TBL_SCHEMAA_TBL A_TBL WHERE A_TBL.YEAR = to_varchar(year_nbr); -- Count the source records.
    
        v_record_count = v_record_count - v_offset_nbr; -- Subtract out the records already committed for the current year. Failsafe if procedure fails
        
        v_commit_count = v_record_count / v_record_per_commit_count; -- Number of times we need to loop
        
        IF v_record_count < v_record_per_commit_count THEN -- Don't enter the loop if it's not necessary
            INSERT INTO B_TBL_SCHEMA.B_TBL (
                SELECT * FROM A_TBL_SCHEMAA_TBL
                WHERE A_TBL.YEAR = to_varchar(year_nbr)
            ); -- Insert into our target table 
            COMMIT;
            
            
            insert into B_TBL_SCHEMA.bulk_load_log values(
                v_table_name,
                to_varchar(year_nbr),
                :v_offset_nbr,
                now()
            ); -- Insert into a logging table to keep up with offset
    
        ELSE
    
            for i in 0..v_commit_count do -- Loop number of commit times. (500 million / 1 million) = 500 commits necessary to process entire table
        
                INSERT INTO B_TBL_SCHEMA.B_TBL (
                    SELECT * FROM A_TBL_SCHEMAA_TBL 
                    WHERE A_TBL.YEAR = to_varchar(year_nbr)
                    LIMIT :v_record_per_commit_count OFFSET :v_offset_nbr
                ); -- Insert into our target table
                COMMIT;
            
                v_offset_nbr = v_offset_nbr + v_record_per_commit_count; -- Update the offset before logging so we know where to begin if procedure fails
                
                insert into B_TBL_SCHEMA.bulk_load_log values(
                    v_table_name,
                    to_varchar(year_nbr),
                    :v_offset_nbr,
                    now()
                ); -- Insert into logging table to keep up with offset
                COMMIT;
            end for;
        end if;
    end for;
end;

我認為在沒有任何額外管理的情況下傳輸表的最簡單和最快的方法是使用BINARY格式選項的EXPORT語句。 這也可以通過架構上的 HANA 工作室上下文菜單或通過File -> Export... -> SAP HANA -> Catalog ObjectsFile -> Import...來完成。

使用這種方法,您可以手動設置導出和導入的線程數,而無需額外的棘手代碼。 在目標系統中導入后,您將擁有與源系統中相同架構中具有相同結構的相同表,因此要將表移動到新名稱或架構,您需要先將其復制到源中。 導入后,您可以在目標表中insert... select...或在源系統中創建具有所需分區的副本表或在目標中重新分區導入的表並將其用作目標表。

有什么優點:

  • 您不需要系統之間的任何代碼或 SDA 連接。
  • 您無需檢查並重新檢查您的代碼是否正常工作並且所有數據都已傳輸且沒有重復。
  • 您將在目標中擁有完全相同的表
  • 表以內部列格式並行導出和導入,因此中間不會出現元組重建(我不知道HANA SDA驅動程序是否足夠聰明,可以通過SDA通道傳輸列並在目標中進行元組重建)。 並且列和記錄數影響不大,只是基數高的列需要時間,空的或基數小的列一眨眼就導出了。

最后,我通過 HANA studio(導入到本地機器)在我的系統中對此進行了測試:具有 130M 記錄和 57 列的 5Gb 大小的表在 6 分鍾內以 8 個線程導出。

您的原始方法如何:您應該始終禁用真正批量操作的刪除索引和約束,並在最后重建/啟用它們,以節省插入期間索引重建或約束檢查的時間。

性能瓶頸可能是僅使用一個線程的 SDA 傳輸。

一種解決方法可能是:

  • 創建一個 function ,其輸入參數為 select 表 A 的子集。例如年份。
  • 將年份列表放入表變量中
  • 調用map_merge以強制並行並將 output 引導到目標表中。

這是一些偽代碼。

-- virtual table to source A over SDA: VT_TBL_A
-- target table B: TBL_B

CREATE OR REPLACE FUNCTION F_TBL_A_YEAR ( IN YEAR INT)
RETURNS TABLE ( ... )
as begin
   select * from VT_TBL_A where year(MY_DT_COLUMN) = :YEAR;
end;

DO
BEGIN
   DECLARE t_var LIKE TBL_B;

   --list of all 'partitions'
   years=select distinct year(MY_DT_COLUMN) as MY_YEAR from VT_TBL_A;

   --call the function for each year
   t_var = MAP_MERGE(:years, F_TBL_A_YEAR( :years.MY_YEAR));

   insert into TBL_B select * from :t_var;
   commit;
END;
 

在此運行時,我建議您檢查系統視圖 M_REMOTE_STATEMENTS 以確認記錄是通過多個連接傳輸的

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM