履歴データテーブルの移行スキーム[Oracleストアドプロシージャに基づく]

履歴書の更新

  • [更新日:20200530]:ストアドプロシージャは、元のリンクに関する情報を見つけるためのインターネットです。コードの観点からは、原則として問題はないようですが、いくつかの小さなローカルの異常がある可能性があります。コメントできるように修正させていただきます。

問題の説明

お客様のサイトには、Oracleベースのビジネスシステムがあります。データベースのバージョンはOracle10g R2(10.2.0.5)Standard Editionであり、データ量は1TBを超えています。

現在、3つの問題があります。

  1. データ量は増え続け、1日あたり3GB以上に達します。
  2. レポートとクエリを含むビジネスシステムの機能は非常に遅く、データをクエリすることさえできません。
  3. RMANのバックアップ圧力は非常に高く、異常な回復はRTO要件を満たすことができません。

問題分析

今回はデータベースに大量のデータがあり、開発者はシーンからフィードバックを受け取り、パフォーマンスが遅いときにインデックスを作成します。ただし、このデータスケールでは、インデックスはあまり効果がありませんが、追加、削除、および変更の効率に影響を与えます。エンタープライズバージョンのパーティションテーブル機能を使用するように既存のデータベースをアップグレードせずに、履歴データベースを確立して、このライブラリのデータを履歴データベースに定期的にアンロードする必要があります。履歴データベースは、年次および月次サブテーブルなどの操作を実装して、大量のデータを含むテーブルの単一テーブルのデータ量を削減できます。

このようにして、ローカルライブラリは制御可能な範囲内にとどまり、履歴ライブラリの異常は生産ラインに影響を与えず、修理時間と圧力も削減できます。
ここに画像の説明を挿入

問題の処理

PL / SQLストアド・プロシージャの定期タスクを使用して、ローカル・ライブラリから履歴データベースにデータを抽出し、アンインストールされたデータをローカル・ライブラリから削除します。一般的なプロセスは次のとおりです。
ここに画像の説明を挿入

  • テストデータを作成する
# 创建测试表
create table operate_log(str01 varchar2(50),cdate varchar2(20));

# 插入测试数据 (将此设置到脚本并设定到计划任务执行,比如30秒执行一次。)
begin
for i in 1..100 loop
INSERT INTO operate_log VALUES(dbms_random.string('x', 20),to_char(SYSDATE,'yyyy-mm-dd hh24:mi:ss'));
end loop;
commit;
end;
/

# 创建测试索引
create index idx_operate_log on operate_log(cdate);
  • ストアドプロシージャ
    お客様の機密保持契約を考慮して、この環境スクリプトを提供することはできません。プレゼンテーションの変更には、オンラインスクリプトのみを使用してください。
    スクリプトの説明:スクリプトは月ごとに分割されており、上の図とはいくつかの違いがあります。
CREATE OR REPLACE 
procedure operate_log_proc(return_code OUT VARCHAR2,return_msg  OUT VARCHAR2) 
authid current_user
is
  err_index           NUMBER;-- 错误定位索引
  table_name          VARCHAR2(20);-- 源分表名称
  log_table_name      VARCHAR2(20);-- 目标分表名称
  current_month_start DATE;
  create_table_cursor NUMBER(10);
  create_table_sql    VARCHAR2(1000);
  insert_data_sql     VARCHAR2(1000);
  delete_data_sql     VARCHAR2(1000);
  v_count 						NUMBER(10);
begin
	table_name  := 'OPERATE_LOG';
  return_msg  := '执行[OPERATE_LOG_PROC]成功';
  return_code := '1';
 
  err_index := 1;
 
  -- 生成分表的表名
  SELECT 'OPERATE_LOG_' ||
         TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1), 'yyyymm')
    INTO log_table_name
    FROM DUAL;
  
  -- 表存在不用创建
	select count(1) into v_count from user_tables where table_name = log_table_name;
  
	if v_count <= 0 THEN
		-- 打开游标
		create_table_cursor := DBMS_SQL.OPEN_CURSOR;
		-- 拼接创建表的SQL语句,并执行
		create_table_sql := 'CREATE TABLE "' || log_table_name || '" (
		"STR01" VARCHAR2(50 BYTE) NOT NULL ,
		"CDATE" VARCHAR2(50 BYTE) NOT NULL
		)';
		DBMS_SQL.PARSE(create_table_cursor, create_table_sql, DBMS_SQL.V7);
		DBMS_SQL.CLOSE_CURSOR(create_table_cursor);
	end if; 
  err_index := 2;
	-- 当前月起始时间,如2020-05-01 00:00:00
  SELECT TRUNC(SYSDATE, 'MM') INTO current_month_start FROM DUAL;
  -- 将Operate_Log表中上月记录添加到新创建的表中
  
  insert_data_sql := 'INSERT INTO ' || log_table_name || ' (SELECT * FROM ' || table_name || ' WHERE CDATE < ''' || current_month_start || ''')';
  dbms_output.put_line('Insert SQL: '||insert_data_sql);
  EXECUTE IMMEDIATE insert_data_sql;
  err_index := 3;
  -- 从Operate_Log表中删除上月记录
  delete_data_sql := 'DELETE FROM ' || table_name || ' WHERE CDATE < ''' || current_month_start || '''';
  dbms_output.put_line('Delete SQL: '||delete_data_sql);
  EXECUTE IMMEDIATE delete_data_sql;
  err_index := 4;
  COMMIT;
EXCEPTION
  WHEN OTHERS THEN
    return_msg  := '过程[OPERATE_LOG_PROC]出错,' || '第[' || err_index || ']块语句出错';
    return_code := '0';
    ROLLBACK;
end operate_log_proc;
/
  • 定期的に実行されるスケジュールされたタスク

実行時間:毎月1日0:30
ここに画像の説明を挿入
オンラインスクリプトの不足:

  1. 操作ログレコードがないと、他のシステムに関連付けて操作結果を出力することはできません。
  2. バッチでの実装はなく、空き時間のある月次履歴データの量が異なります。10W回線レコードの1回限りの操作と1000W回線レコードの1回限りの操作のパフォーマンスは完全に異なります。

一般的な問題

  1. 履歴データが移行された後、アプリケーションはどのようにクエリを実行しますか?
    サブメータの状況に応じて、アプリケーションプログラムを変更する必要があります。インターフェイスのクエリ間隔を使用して、アプリケーションによって発行されたSQLが2つのデータベースにまたがっているかどうかを判断します。クエリ間隔がFanku保持期間を超えない場合は、SQLプラン1を実行し、クエリ間隔がFanku保持期間を超える場合はSQLを実行します。プラン2。クエリ間隔にはこれが含まれていません。データベース保持期間はSQLスキーム3を実行します。
完整数据 = 生产数据 + 历史数据

おすすめ

転載: blog.csdn.net/weixin_38623994/article/details/106408434