Oracleでの論理削除
@mogmet
2016/05/10 Database Connect 2016
About me
• twitter: @mogmet
• 好物:iOS, php, MySQL, Oracle
• 仕事:インフラエンジニア→iOSエンジニア→フリーランスなDBA
• ブログとか: http://mogmet.com/
• 作ったアプリたち↓
ワンナイト人狼 for iPhone STARBUCKSHOLIC
はじめてのOracleの
発表です
論理削除戦争
#ronsakucasual DBの論理削除についてひたすら
共有する 論理削除 Casual Talks #1 にいってきた
まとめ
http://blog.mogmet.com/ronsakucasual-1/
様々な方法の参考
考えに考え、結果、削除フラグを採用
することになった皆さんへ朗報です
12c 新機能
In-Database Archiving
(インデータベース・アーカイブ
)
これを使うと論理削除を
Oracleの機能として実現でき
る!
有効にするには
ALTER TABLE <table_name> ROW ARCHIVAL;
を実行するだけ!
※新規の時はtableを作る時にROW ARCHIVALをつけるだけ。
有効化すると
ORA_ARCHIVE_STATE
という非表示のvarchar2型の列が追加されるので
それを削除フラグとして使う
SQL> create table anohana(id number, name varchar(32)
Table created.
SQL> insert into anohana values (1, 'jintan');
1 row created.
SQL> insert into anohana (id, name, ORA_ARCHIVE_STATE) v
1 row created.
SQL> commit;
Commit complete.
SQL> select * from anohana;
ID NAME
---------- --------------------
1 jintan
menmaが見当たらない!
魔法のコトバを唱える
QL> ALTER SESSION SET ROW ARCHIVAL VISIBILITY = A
SQL> select * from anohana;
ID NAME
---------- --------------------
1 jintan
2 menma
見つかっちゃった
(๑ゝ‫◕ڡ‬๑)
In-Database Archivingを有効にした
テーブルに対して実行計画をとってみる
と
実行計画をみるとSQLが
自動的に付与されていたのがわかる
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2033 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| ANOHANA | 1 | 2033 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ANOHANA"."ORA_ARCHIVE_STATE"='0' AND "ID"<3)
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 62 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| ANOHANA | 2 | 62 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ID"<3)
ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ALL;
SELECT * FROM anohana
WHERE id < 3;
SELECT * FROM anohana
WHERE id < 3;
Tips
インデータベースアーカイブが
有効(VISIBILITY = ACTIVE)な時に
ORA_ARCHIVE_STATEを条件にいれて
SELECTしても全くデータが
でないので注意!
SQL> SELECT * FROM anohana WHERE ORA_ARCHIVE_STATE =
1;
no rows selected
SQL> ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ALL;
Session altered.
SQL> SELECT * FROM anohana WHERE ORA_ARCHIVE_STATE =
1;
ID NAME
---------- --------------------
2 menma
CHECK制約を
ORA_ARCHIVE_STATE
に追加することもできます
!
SQL> ALTER TABLE anohana ADD CONSTRAINT check_state
CHECK (ora_archive_state IN ('1', '0'));
Table altered.
SQL> INSERT INTO anohana (id, name, ORA_ARCHIVE_STATE)
VALUES (1, 'yukiatsu', 2);
INSERT INTO anohana (id, name, ORA_ARCHIVE_STATE)
VALUES (1, 'yukiatsu', 2)
*
ERROR at line 1:
ORA-02290: check constraint (HOGE.CHECK_STATE) violated
まとめ
まとめ
• 論理削除を実装する際にはインデータベース・
アーカイブを用いるとアプリの実装コストを
下げられそう
• varchar2の型でORA_ARCHIVE_STATEは
使えるので使い方によっては様々な情報を
工夫して入れられそう
One more thing…
個人的にはDB全般において論理削除を
使う話になった時はもう少し詰めて設計を考えて、
使わないで済むならその方がいいと思っている
御静聴ありがとうございました

Oracle In-database-archiving ~Oracleでの論理削除~