履歴書の更新
- [更新日:20200530]:ストアドプロシージャは、元のリンクに関する情報を見つけるためのインターネットです。コードの観点からは、原則として問題はないようですが、いくつかの小さなローカルの異常がある可能性があります。コメントできるように修正させていただきます。
問題の説明
お客様のサイトには、Oracleベースのビジネスシステムがあります。データベースのバージョンはOracle10g R2(10.2.0.5)Standard Editionであり、データ量は1TBを超えています。
現在、3つの問題があります。
- データ量は増え続け、1日あたり3GB以上に達します。
- レポートとクエリを含むビジネスシステムの機能は非常に遅く、データをクエリすることさえできません。
- 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
オンラインスクリプトの不足:
- 操作ログレコードがないと、他のシステムに関連付けて操作結果を出力することはできません。
- バッチでの実装はなく、空き時間のある月次履歴データの量が異なります。10W回線レコードの1回限りの操作と1000W回線レコードの1回限りの操作のパフォーマンスは完全に異なります。
一般的な問題
- 履歴データが移行された後、アプリケーションはどのようにクエリを実行しますか?
サブメータの状況に応じて、アプリケーションプログラムを変更する必要があります。インターフェイスのクエリ間隔を使用して、アプリケーションによって発行されたSQLが2つのデータベースにまたがっているかどうかを判断します。クエリ間隔がFanku保持期間を超えない場合は、SQLプラン1を実行し、クエリ間隔がFanku保持期間を超える場合はSQLを実行します。プラン2。クエリ間隔にはこれが含まれていません。データベース保持期間はSQLスキーム3を実行します。
完整数据 = 生产数据 + 历史数据