5.3 Oracle Databaseのデータの有効性および表示の制御
インデータベース・アーカイブおよび時間的な有効性を使用して、Oracle Databaseのデータの有効性および表示を制御できます。
この項では、次の項目について説明します。
5.3.1 インデータベース・アーカイブの使用
インデータベース・アーカイブでは、表内の行をアクティブまたはアーカイブ済としてマークできます。
インデータベース・アーカイブはどのようにデータベース操作とアプリケーション操作に役立つか
インデータベース・アーカイブの利点を次に示します。
- インデータベース・アーカイブを使用すると、アプリケーションのパフォーマンスが低下することなく、大量のアーカイブ・データをデータベースに格納できます。
- アーカイブ済データを圧縮するとバックアップ・パフォーマンスが向上します。
- データ検索のパフォーマンス・アクセラレータとして使用できます。
これにより、検索の範囲が、現在関連性のあるものに絞り込まれます(ターゲット表内のデータ量が少数の可能性がある)。
- データ変更を伴うアプリケーション・アップグレードによる停止時間を短縮できます。
アクティブ・データとアーカイブ済データを別々に処理するようにアップグレード・スクリプトを記述できます。たとえば、アーカイブ済データはユーザーには不可視であるため、アップグレードしアクティブ・データにデータ修正が適用された直後に再度アプリケーションが使用可能になるようにすることができます。アーカイブ済データに対する変更は後に延期できます。
アクティブ・データとアーカイブ・データ
インデータベース・アーカイブの目的のために、表内の行は、次の2つのうちどちらかの状態になっています:
-
アクティブ - 頻繁な問合せの対象となる行は、通常はアクティブとみなされます。たとえば、ビジネス環境においては、現四半期と前四半期の売上データがアクティブとみなされる可能性があります。
-
アーカイブ - 進行中のアクティビティに必要でなくなったデータを含む行は、暗黙的にアーカイブとみなされる可能性があります。たとえば、それらには、記録保存やコンプライアンスの目的でのみ格納されている数か月前または数年前に完了したトランザクションからのデータが含まれている可能性があります。このようなデータが読み取られることや変更されることはめったにありません。たとえば、過去5年の事業年度の売上データをアーカイブ・データとみなすことができます。
多くの場合、データベース内のデータの大部分は、非アクティブであるため、アーカイブとなります。問合せでこのデータを自動的にフィルタ処理すると、問合せのパフォーマンスが大幅に向上します。同様に、バルク更新(アプリケーションのアップグレード中など)でも、無関係なデータが除外されて停止時間が短くなることでメリットがあります。このデータ・フィルタ処理を設定するには、表に対して行アーカイブ格納を有効にします。これにより、列ORA_ARCHIVE_STATE
がその表に追加されます。アーカイブ済の行は通常は問合せでは参照不可であるため、これらの行は処理されず、問合せ結果から除外されます。
ORA_ARCHIVE_STATEとは
ORA_ARCHIVE_STATE
は、指定された行をactive
またはarchived
として指定する役目を果たすシステム列です。これは、ディクショナリ内にユーザー列番号(usrcol#
)がない非表示列です。これは、表のDESCRIBE
を実行したときや表に対してSELECT *
問合せを発行したときには参照不可です。ただし、この列は、SELECT
問合せの選択リスト、UPDATE
問合せの変更リスト、および問合せとDMLの述語で、明示的に指定できます。
ノート:
ご自分で、およびご自分の組織のILM慣例で、行アーカイブ表内のどの行をアーカイブする必要があるかを決める必要があります。インデータベース・アーカイブでは、このような分析は実行されません。デフォルトでは、行アーカイブ表内の各行がアクティブとなります。新しい表または既存の表での行アーカイブの有効化
CREATE TABLE
文にROW ARCHIVAL
句を含めるか、ALTER TABLE
を使用して既存の表にROW ARCHIVAL
を設定します。たとえば:
CREATE TABLE scott.emp (EMPNO NOT NULL NUMBER(7), FULLNAME VARCHAR2(100), JOB VARCHAR2(9), MGR NUMBER(7)) ROW ARCHIVAL;
ALTER TABLE scott.emp ROW ARCHIVAL;
表からROW ARCHIVAL
プロパティを削除することもできます。これにより、表からORA_ARCHIVE_STATE
列が削除されます。
ALTER TABLE scott.emp NO ROW ARCHIVAL;
ノート:
オンライン再定義の間に表の行アーカイブ属性を削除することはできません。
ORA_ARCHIVE_STATE
列の特性の一部を次に示します:
- これは、
SELECT *
問合せおよびDESCRIBE
コマンドによって暗黙的にレポートされない非表示列です。 - この列は明示的に更新できます。
行アーカイブが有効になっている表への問合せ
行アーカイブが有効になっている表に対してINSERT
、UPDATE
およびCREATE AS SELECT
を使用した場合の動作に留意してください。
各行のORA_ARCHIVE_STATE
のデフォルト値は0です。これは、行はその列値をアーカイブ済に変更するまでアクティブ・データとみなされるということです。したがって、行アーカイブ表へのINSERTでは、必ず、新しい行がアクティブに設定されます。
UPDATE
更新では、どの行のORA_ARCHIVE_STATE
値も直接設定できます。規則ではactive
またはarchived
を示すために"0"または"1"を使用することになっていますが、ORA_ARCHIVE_STATE
を任意の有効なVARCHAR2(4000)値に更新できます。
CREATE TABLE AS SELECT
の動作は、選択範囲内の各表が行アーカイブに対応しているかどうかと、SELECT
リスト内の列の構造によって異なります。(次の表を参照)
"ORA_ARCHIVE_STATE"はOracle予約語ではないため各表で行アーカイブがまだ有効になっていない場合はユーザー列の名前として使用できることに注意してください。
INSERT INTO SELECT
ソース表とターゲット表が行アーカイブに対応しているINSERT INTO SELECT
では、ソース表とターゲット表の列リストで明示的にマップされていないかぎり、ターゲット表のORA_ARCHIVE_STATE列にソース表の対応する列の値が移入されることはありません。かわりに、デフォルトのアクティブの行アーカイブ状態が設定されます。
ALTER TABLE MOVE
ALTER TABLE MOVE
を使用して表を移動した場合、表の行アーカイブ状態列は保持されます。
CREATE TABLE AS SELECTでの2つの表の間のデータ転送の動作の違い(両方の表が行アーカイブ対応の場合とそうでない場合)
次の表では、様々なシナリオでのCREATE TABLE AS SELECT
の動作を示します。
表5-3 ORA_ARCHIVE_STATEの属性
ソース表が行アーカイブ対応かどうか | ターゲット表が行アーカイブ対応かどうか | 選択リストの構造 | ORA_ARCHIVE_STATEはソース表のユーザー列である | 動作 |
---|---|---|---|---|
いいえ | いいえ | SELECT * であるか、ORA_ARCHIVE_STATE を含めることがSELECTリストで明示的に指定されている
|
可 | ORA_ARCHIVE_STATE をユーザー列として含め、すべての行をターゲット表のリクエストされた列にコピーします。
|
可 | いいえ | SELECT * |
いいえ | 選択された行を、行の可視性に応じて、ORA_ARCHIVE_STATE 列を除くすべての列にコピーします。
|
可 | いいえ | ORA_ARCHIVE_STATE がSELECTリストに明示的に含まれている
|
可 | ORA_ARCHIVE_STATE をユーザー列として含め、選択された行を、行の可視性に応じて、リクエストされた列にコピーします。
|
可 | 可 | SELECT * |
いいえ | すべての行を、ターゲット表のリクエストされた列にコピーします。ターゲット表内のすべての新規行のORA_ARCHIVE_STATE 列に'0'を割り当てます。
|
可 | 可 | ORA_ARCHIVE_STATE がSELECT リストに明示的に含まれている
|
いいえ | 選択された行を、行の可視性に応じて、リクエストされた列にコピーします。各行の既存の行アーカイブ状態をソース表からターゲット表に伝播します。 |
可 | 可 | ORA_ARCHIVE_STATE がSELECT に明示的に含まれていない
|
いいえ | 選択された行を、行の可視性に応じて、選択された列にコピーします。ターゲット表内のすべての新規行の新しいORA_ARCHIVE_STATE 列に'0'を割り当てます。
|
いいえ | 可 | SELECT * であるか、ORA_ARCHIVE_STATE がSELECTリストに明示的に含まれている
|
可 |
重要: 戻り値
|
セッション・レベルの可視性制御のためのROW ARCHIVAL VISIBILITY
の設定
デフォルトでは、行アーカイブが有効になっている表においては、アクティブ・データのみをユーザーおよびアプリケーションが参照可能です。ただし、これをセッションごとに変更することや、アーカイブ済の行を現在のセッション内で参照可能にする(または参照不可に戻す)ことができます。
ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ACTIVE;
ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ALL;
関連項目:
- 『PL/SQLパッケージおよびタイプ・リファレンス』では、
DBMS_ILM
パッケージに、ORA_ARCHIVE_STATE
列のためのアクティブおよびアーカイブ済状態定数が含まれています。これらは、それぞれ'0
'と'1
'で表されます。
DBMS_ILMでは、archive_state_active constant varchar2(1) := '0'; archive_state_archived constant varchar2(1) := '1';
ORA_ARCHIVE_STATE
の現在の値を返すための関数ARCHIVESTATENAME
も提供されています。function archiveStateName(value in varchar2) return varchar2;
入力パラメータ 説明 value アーカイブ状態名を返す必要がある文字列値。 return "0"の場合は"archive_state_active"
その他の場合は"archive_state_archived"
- 『SQL言語リファレンス』では、
ALTER TABLE
文とCREATE TABLE
文でのROW_ARCHIVAL
句の使用について説明しています。ALTER TABLE [schema.]table [alter_table_properties | … ] [row_archival_clause]
CREATE TABLE [schema.]table [(relational properties)] [table properties] table_properties::= [column_properties ] [ table_partitioning_clauses ] … [row_archival_clause] row_archival_clause ::= [NO] ROW ARCHIVAL
例5-10 インデータベース・アーカイブの使用
/* Set visibility to ACTIVE to display only active rows of a table.*/ ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ACTIVE; CREATE TABLE employees_indbarch (employee_id NUMBER(6) NOT NULL, first_name VARCHAR2(20), last_name VARCHAR2(25) NOT NULL, email VARCHAR2(25) NOT NULL, phone_number VARCHAR2(20), hire_date DATE NOT NULL, job_id VARCHAR2(10) NOT NULL, salary NUMBER(8,2), commission_pct NUMBER(2,2), manager_id NUMBER(6), department_id NUMBER(4)) ROW ARCHIVAL; /* Show all the columns in the table, including hidden columns */ SELECT SUBSTR(COLUMN_NAME,1,22) NAME, SUBSTR(DATA_TYPE,1,20) DATA_TYPE, COLUMN_ID AS COL_ID, SEGMENT_COLUMN_ID AS SEG_COL_ID, INTERNAL_COLUMN_ID AS INT_COL_ID, HIDDEN_COLUMN, CHAR_LENGTH FROM USER_TAB_COLS WHERE TABLE_NAME='EMPLOYEES_INDBARCH'; NAME DATA_TYPE COL_ID SEG_COL_ID INT_COL_ID HID CHAR_LENGTH ---------------------- -------------------- ---------- ---------- ---------- --- ----------- ORA_ARCHIVE_STATE VARCHAR2 1 1 YES 4000 EMPLOYEE_ID NUMBER 1 2 2 NO 0 FIRST_NAME VARCHAR2 2 3 3 NO 20 LAST_NAME VARCHAR2 3 4 4 NO 25 EMAIL VARCHAR2 4 5 5 NO 25 PHONE_NUMBER VARCHAR2 5 6 6 NO 20 HIRE_DATE DATE 6 7 7 NO 0 JOB_ID VARCHAR2 7 8 8 NO 10 SALARY NUMBER 8 9 9 NO 0 COMMISSION_PCT NUMBER 9 10 10 NO 0 MANAGER_ID NUMBER 10 11 11 NO 0 DEPARTMENT_ID NUMBER 11 12 12 NO 0 /* Insert some data into the table */ INSERT INTO employees_indbarch(employee_id, first_name, last_name, email, hire_date, job_id, salary, manager_id, department_id) VALUES (251, 'Scott', 'Tiger', 'scott.tiger@example.com', '21-MAY-2009', 'IT_PROG', 50000, 103, 60); INSERT INTO employees_indbarch(employee_id, first_name, last_name, email, hire_date, job_id, salary, manager_id, department_id) VALUES (252, 'Jane', 'Lion', 'jane.lion@example.com', '11-JUN-2009', 'IT_PROG', 50000, 103, 60); /* Decrease the ORA_ARCHIVE_STATE column size to improve formatting in queries */ COLUMN ORA_ARCHIVE_STATE FORMAT a18; /* The default value for ORA_ARCHIVE_STATE is '0', which means active */ SELECT employee_id, ORA_ARCHIVE_STATE FROM employees_indbarch; EMPLOYEE_ID ORA_ARCHIVE_STATE ----------- ------------------ 251 0 252 0 /* Insert a value into ORA_ARCHIVE_STATE to set the record to inactive status*/ UPDATE employees_indbarch SET ORA_ARCHIVE_STATE = '1' WHERE employee_id = 252; /* Only active records are in the following query */ SELECT employee_id, ORA_ARCHIVE_STATE FROM employees_indbarch; EMPLOYEE_ID ORA_ARCHIVE_STATE ----------- ------------------ 251 0 /* Set visibility to ALL to display all records */ ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ALL; SELECT employee_id, ORA_ARCHIVE_STATE FROM employees_indbarch; EMPLOYEE_ID ORA_ARCHIVE_STATE ----------- ------------------ 251 0 252 1
5.3.2 時間的な有効性の使用
時間的な有効性は、実際の有効性の期間を追跡できます。有効時間はデータのユーザーおよびアプリケーションによって設定でき、指定された有効時間または有効な時間範囲でデータを選択できます。
多くの場合、アプリケーションは、ビジネスの管理に関連する日付またはタイムスタンプでデータベースに記録されるファクトの有効性を示します。たとえば、保険業の補償の有効日を決定する人事管理(HR)アプリケーションの従業員の雇用日は有効な日付です。この日付は、従業員レコードがデータベースに入力された日付または時間とは異なります。前者の一時属性(雇用日)は有効時間(VT)と呼ばれ、後者(データベースに入力された日付)はトランザクション時間(TT)と呼ばれます。有効時間は通常ユーザーによって制御されますが、トランザクション時間はシステムが管理します。
ILMでは、有効時間属性は、ファクトが実業界で有効な時間および無効な時間を示すことができます。有効時間属性を使用すると、問合せは現在有効な行のみを表示できますが、閉じた注文や将来の雇用などの現在有効でないファクトを含む行は表示できません。
有効時間時制モデリングに不可欠な概念は次のとおりです。
-
有効期間
これは時間のユーザー定義表現です。有効時間の例には、プロジェクトの開始日および終了日、従業員の雇用日および退職日が含まれます。
-
有効時間セマンティックを使用した表
これらの表にはユーザー定義時間の1つ以上のディメンションがあり、それぞれ開始と終了があります。
-
有効時間フラッシュバック問合せ
これは、有効時間ディメンションを使用して、ある時点および複数バージョンの問合せを実行する機能です。
有効期間は、表定義で指定された2つの日時列で構成されます。列を明示的に追加して有効期間を追加したり、列を自動的に作成できます。表の作成または表の変更プロセス中に有効期間を追加できます。
一時的な表問合せのセッション・レベルの表示制御をサポートするため、DBMS_FLASHBACK_ARCHIVE
PL/SQLパッケージはENABLE_AT_VALID_TIME
プロシージャを提供します。プロシージャを実行するには、必要なシステムおよびオブジェクト権限が必要です。
次のPL/SQLプロシージャは、指定された時点で有効時間の表示を設定します。
SQL> EXECUTE DBMS_FLASHBACK_ARCHIVE.enable_at_valid_time ('ASOF', '31-DEC-12 12.00.01 PM');
次のPL/SQLプロシージャは、セッション・レベルで有効期間内の現在有効なデータに一時的なデータの表示を設定します。
SQL> EXECUTE DBMS_FLASHBACK_ARCHIVE.enable_at_valid_time('CURRENT');
次のプロシージャは、デフォルトの一時的な表の表示である全表の一時的なデータの表示を設定します。
SQL> EXECUTE DBMS_FLASHBACK_ARCHIVE.enable_at_valid_time('ALL');
関連項目:
-
Oracle Temporalの詳細は、『Oracle Database開発ガイド』を参照してください
-
DBMS_FLASHBACK_ARCHIVE
パッケージの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください -
CREATE
TABLE
またはALTER
TABLE
を使用した有効時間の一時モデリングの開始の詳細は、『Oracle Database SQL言語リファレンス』を参照してください -
表情報の監視に使用するビューの詳細は、『Oracle Databaseリファレンス』を参照してください
5.3.3 時間的な有効性による表の作成
このトピックの例は、時間的な有効性による表の作成方法を示します。
例5-11に、時間的な有効性の使用を示します。
Live SQL:
関連する例をOracle Live SQLのOracle Live SQL: 時間的な有効性による表の作成で参照して実行してください。
例5-11 時間的な有効性による表の作成
/* Create a time with an employee tracking timestamp */ /* using the specified columns*/ CREATE TABLE employees_temp ( employee_id NUMBER(6) NOT NULL, first_name VARCHAR2(20), last_name VARCHAR2(25) NOT NULL, email VARCHAR2(25) NOT NULL, phone_number VARCHAR2(20), hire_date DATE NOT NULL, job_id VARCHAR2(10) NOT NULL, salary NUMBER(8,2), commission_pct NUMBER(2,2), manager_id NUMBER(6), department_id NUMBER(4), PERIOD FOR emp_track_time); DESCRIBE employees_temp Name Null? Type ------------------------------------------------------- -------- --------------- EMPLOYEE_ID NOT NULL NUMBER(6) FIRST_NAME VARCHAR2(20) LAST_NAME NOT NULL VARCHAR2(25) EMAIL NOT NULL VARCHAR2(25) PHONE_NUMBER VARCHAR2(20) HIRE_DATE NOT NULL DATE JOB_ID NOT NULL VARCHAR2(10) SALARY NUMBER(8,2) COMMISSION_PCT NUMBER(2,2) MANAGER_ID NUMBER(6) DEPARTMENT_ID NUMBER(4) SQL> SELECT SUBSTR(COLUMN_NAME,1,22) NAME, SUBSTR(DATA_TYPE,1,28) DATA_TYPE, COLUMN_ID AS COL_ID, SEGMENT_COLUMN_ID AS SEG_COL_ID, INTERNAL_COLUMN_ID AS INT_COL_ID, HIDDEN_COLUMN FROM USER_TAB_COLS WHERE TABLE_NAME='EMPLOYEES_TEMP'; NAME DATA_TYPE COL_ID SEG_COL_ID INT_COL_ID HID ---------------------- ---------------------------- ------ ---------- ---------- --- EMP_TRACK_TIME_START TIMESTAMP(6) WITH TIME ZONE 1 1 YES EMP_TRACK_TIME_END TIMESTAMP(6) WITH TIME ZONE 2 2 YES EMP_TRACK_TIME NUMBER 3 YES EMPLOYEE_ID NUMBER 1 3 4 NO FIRST_NAME VARCHAR2 2 4 5 NO LAST_NAME VARCHAR2 3 5 6 NO EMAIL VARCHAR2 4 6 7 NO PHONE_NUMBER VARCHAR2 5 7 8 NO HIRE_DATE DATE 6 8 9 NO JOB_ID VARCHAR2 7 9 10 NO SALARY NUMBER 8 10 11 NO COMMISSION_PCT NUMBER 9 11 12 NO MANAGER_ID NUMBER 10 12 13 NO DEPARTMENT_ID NUMBER 11 13 14 NO /* Insert/update/delete with specified values for time columns */ INSERT INTO employees_temp(emp_track_time_start, emp_track_time_end, employee_id, first_name, last_name, email, hire_date, job_id, salary, manager_id, department_id) VALUES (TIMESTAMP '2009-06-01 12:00:01 Europe/Paris', TIMESTAMP '2012-11-30 12:00:01 Europe/Paris', 251, 'Scott', 'Tiger', 'scott.tiger@example.com', DATE '2009-05-21', 'IT_PROG', 50000, 103, 60); INSERT INTO employees_temp(emp_track_time_start, emp_track_time_end, employee_id, first_name, last_name, email, hire_date, job_id, salary, manager_id, department_id) VALUES (TIMESTAMP '2009-06-01 12:00:01 Europe/Paris', TIMESTAMP '2012-12-31 12:00:01 Europe/Paris', 252, 'Jane', 'Lion', 'jane.lion@example.com', DATE '2009-06-11', 'IT_PROG', 50000, 103, 60); UPDATE employees_temp set salary = salary + salary * .05 WHERE emp_track_time_start <= TIMESTAMP '2009-06-01 12:00:01 Europe/Paris'; SELECT employee_id, SALARY FROM employees_temp; EMPLOYEE_ID SALARY ----------- ---------- 251 52500 252 52500 /* No rows are deleted for the following statement because no records */ /* are in the specified track time. */ DELETE employees_temp WHERE emp_track_time_end < TIMESTAMP '2001-12-31 12:00:01 Europe/Paris'; 0 rows deleted. /* Show rows that are in a specified time period */ SELECT employee_id FROM employees_temp WHERE emp_track_time_start > TIMESTAMP '2009-05-31 12:00:01 Europe/Paris' AND emp_track_time_end < TIMESTAMP '2012-12-01 12:00:01 Europe/Paris'; EMPLOYEE_ID ----------- 251 /* Show rows that are in a specified time period */ SELECT employee_id FROM employees_temp AS OF PERIOD FOR emp_track_time TIMESTAMP '2012-12-01 12:00:01 Europe/Paris'; EMPLOYEE_ID ----------- 252