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コマンドによって暗黙的にレポートされない非表示列です。
  • この列は明示的に更新できます。

行アーカイブが有効になっている表への問合せ

行アーカイブが有効になっている表に対してINSERTUPDATEおよびCREATE AS SELECTを使用した場合の動作に留意してください。

INSERT

各行のORA_ARCHIVE_STATEのデフォルト値は0です。これは、行はその列値をアーカイブ済に変更するまでアクティブ・データとみなされるということです。したがって、行アーカイブ表へのINSERTでは、必ず、新しい行がアクティブに設定されます。

UPDATE

更新では、どの行のORA_ARCHIVE_STATE値も直接設定できます。規則ではactiveまたはarchivedを示すために"0"または"1"を使用することになっていますが、ORA_ARCHIVE_STATEを任意の有効なVARCHAR2(4000)値に更新できます。

CREATE TABLE AS SELECT

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_STATESELECTリストに明示的に含まれている いいえ 選択された行を、行の可視性に応じて、リクエストされた列にコピーします。各行の既存の行アーカイブ状態をソース表からターゲット表に伝播します。
ORA_ARCHIVE_STATESELECTに明示的に含まれていない いいえ 選択された行を、行の可視性に応じて、選択された列にコピーします。ターゲット表内のすべての新規行の新しい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'で表されます。
    archive_state_active constant varchar2(1) := '0'; 
    archive_state_archived constant varchar2(1) := '1'; 
    DBMS_ILMでは、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');

関連項目:

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

5.3.4 インデータベース・アーカイブおよび時間的な有効性の制限事項

このトピックでは、インデータベース・アーカイブおよび時間的な有効性に関連付けられている制限事項を示します。

次のような制限があります。

  • ILMは、時間的な有効性のOLTP表圧縮でサポートされていません。セグメント・レベルのILMおよび圧縮は、終了時間列でパーティション化される場合にサポートされます。

  • ILMは、インデータベース・アーカイブのOLTP表圧縮でサポートされていません。セグメント・レベルのILMおよび圧縮は、ORA_ARCHIVE_STATE列でパーティション化される場合にサポートされます。