您好,欢迎访问一九零五行业门户网

【Oracle Database 12c New Feature】ILM – In-Database

本文介绍oracle database 12c中关于数据生命周期管理多个新特性中相对最简单的一个,数据库内归档(in-database archiving)。使用的测试表是上一篇介绍数据时间有效期管理中使用的tv表(包括表结构和测试数据),如果你还没有看过上一篇文章,可以先阅读【o
本文介绍oracle database 12c中关于数据生命周期管理多个新特性中相对最简单的一个,数据库内归档(in-database archiving)。使用的测试表是上一篇介绍数据时间有效期管理中使用的tv表(包括表结构和测试数据),如果你还没有看过上一篇文章,可以先阅读【oracle database 12c new feature】ilm – temporal validity。
相比起数据时间有效期管理而言,数据库内归档非常简单,只有一个开关,对于一条数据,要不就是活跃的允许显示,要不就是归档掉不显示,这是由数据库管理员来人工操作的。
在设置数据库内归档之前,必须要在表级别启用该特性。如上一篇文章提到的,in-database archiving支持多租户架构,可以在pdb中使用。
sql> alter table tv row archival; table altered.
oracle仍然是使用隐藏列来实现这个功能的,在启用该特性以后,会自动在表上增加ora_archive_state字段,这是一个varchar2(4000)的字段。
sql> select column_name,data_type,hidden_column from user_tab_cols where table_name='tv'; column_name data_type hid-------------------- -------------------- ---ora_archive_state varchar2 yessys_nc00005$ raw yesvalid_time_end date yesvalid_time_start date yesinsert_time date novalid_time number yes 6 rows selected.
先检查一下tv表中的数据分布,一共有9个不同的时间段,前面5个都只有1条记录,后面4个则有大量测试记录。
sql> select insert_time,count(*) from tv group by insert_time order by 1; insert_time count(*)----------------- ----------20130811 09:04:30 120130811 09:08:27 120130811 09:22:30 120130811 09:39:40 120130811 09:45:22 120130811 09:50:44 1936820130811 09:50:46 1936820130811 09:50:47 1936820130811 09:50:48 19368 9 rows selected.
尝试将所有20130811 09:50之后的记录全部设置为归档模式。直接使用update语句将ora_archive_state字段更新为任意非0的字符,0表示该记录是活跃的,任何非0字符都表示该记录被归档。
sql> update tv set ora_archive_state = '20' where insert_time>to_date('20130811 09:50','yyyymmdd hh24:mi'); 77472 rows updated.
再次执行相同的查询语句,可以看到只存在活跃的5条记录了。
sql> select insert_time,count(*) from tv group by insert_time order by 1; insert_time count(*)----------------- ----------20130811 09:04:30 120130811 09:08:27 120130811 09:22:30 120130811 09:39:40 120130811 09:45:22 1 5 rows selected.
可以在会话级别设置即使是记录被归档,也仍然显示出来。
sql> alter session set row archival visibility = all; session altered. sql> select insert_time,count(*) from tv group by insert_time order by 1; insert_time count(*)----------------- ----------20130811 09:04:30 120130811 09:08:27 120130811 09:22:30 120130811 09:39:40 120130811 09:45:22 120130811 09:50:44 1936820130811 09:50:46 1936820130811 09:50:47 1936820130811 09:50:48 19368 9 rows selected.
检查ora_archive_state值,可以看到所有活跃数据的ora_archive_state字段值均为0,这也是在表级别启用数据库内归档以后的默认值。
sql> select ora_archive_state,insert_time,count(*) from tv group by ora_archive_state,insert_time order by 2; ora_archive_state insert_time count(*)-------------------- ----------------- ----------0 20130811 09:04:30 10 20130811 09:08:27 10 20130811 09:22:30 10 20130811 09:39:40 10 20130811 09:45:22 120 20130811 09:50:44 1936820 20130811 09:50:46 1936820 20130811 09:50:47 1936820 20130811 09:50:48 19368 9 rows selected.
将其中的一些记录的ora_archive_state字段更新为另外的非0字符。
sql> update tv set ora_archive_state='archiving' where insert_time='20130811 09:50:48'; 19368 rows updated. sql> select ora_archive_state,insert_time,count(*) from tv group by ora_archive_state,insert_time order by 2; ora_archive_state insert_time count(*)-------------------- ----------------- ----------0 20130811 09:04:30 10 20130811 09:08:27 10 20130811 09:22:30 10 20130811 09:39:40 10 20130811 09:45:22 120 20130811 09:50:44 1936820 20130811 09:50:46 1936820 20130811 09:50:47 19368archiving 20130811 09:50:48 19368
在会话级别重新设置不显示归档数据,可以看到只要是ora_archive_state字段不为0的记录都不会显示。
sql> alter session set row archival visibility = active; session altered. sql> select insert_time,count(*) from tv group by insert_time order by 1; insert_time count(*)----------------- ----------20130811 09:04:30 120130811 09:08:27 120130811 09:22:30 120130811 09:39:40 120130811 09:45:22 1
性能考虑,这一点数据库内归档与时间有效性是相同的,都只是对隐藏字段进行了filter操作。即使是只显示活跃数据,也仍然需要扫描全表。这一点在真实应用中可以通过创建索引来避免全表扫描,可以参看mos note: potential sql performance degradation when in database row archiving (doc id 1579790.1),也就是数据库内归档只应该在一个具备良好性能的sql基础上对返回结果进行过滤,而不要期望归档的记录不参与扫描。
sql> select * from tv; insert_time-----------------20130811 09:04:3020130811 09:08:2720130811 09:22:3020130811 09:39:4020130811 09:45:22  execution plan----------------------------------------------------------plan hash value: 1723968289 --------------------------------------------------------------------------| id | operation | name | rows | bytes | cost (%cpu)| time |--------------------------------------------------------------------------| 0 | select statement | | 4 | 8044 | 102 (0)| 00:00:01 ||* 1 | table access full| tv | 4 | 8044 | 102 (0)| 00:00:01 |-------------------------------------------------------------------------- predicate information (identified by operation id):---------------------------------------------------  1 - filter(tv.ora_archive_state='0') note----- - dynamic statistics used: dynamic sampling (level=2)  statistics---------------------------------------------------------- 0 recursive calls 0 db block gets 375 consistent gets 0 physical reads 0 redo size 648 bytes sent via sql*net to client 543 bytes received via sql*net from client 2 sql*net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 5 rows processed
数据库内归档可以跟时间有效性管理一起配合使用。在会话级别激活时间有效性,可以看到检索不再返回任何数据。执行计划中显示filter条件融合了数据库内归档跟时间有效性两层过滤。
sql> exec dbms_flashback_archive.enable_at_valid_time('current'); pl/sql procedure successfully completed. sql> select * from tv; no rows selected  execution plan----------------------------------------------------------plan hash value: 1723968289 --------------------------------------------------------------------------| id | operation | name | rows | bytes | cost (%cpu)| time |--------------------------------------------------------------------------| 0 | select statement | | 3 | 6087 | 102 (0)| 00:00:01 ||* 1 | table access full| tv | 3 | 6087 | 102 (0)| 00:00:01 |-------------------------------------------------------------------------- predicate information (identified by operation id):---------------------------------------------------  1 - filter(t.ora_archive_state='0' and (t.valid_time_start is null or sys_extract_utc(internal_function(t.valid_time_start))sys_extract_utc (systimestamp(6))))  statistics---------------------------------------------------------- 34 recursive calls 8 db block gets 397 consistent gets 0 physical reads 0 redo size 347 bytes sent via sql*net to client 532 bytes received via sql*net from client 1 sql*net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 0 rows processed
将时间有效期设置为20130811 09:39:50,根据上一篇文章我们设置的1分钟有效期,只有在20130811 09:39:40插入的这条活跃记录可以被显示出来。
sql> exec dbms_flashback_archive.enable_at_valid_time('asof',to_date('20130811 09:39:50','yyyymmdd hh24:mi:ss')); pl/sql procedure successfully completed. sql> select * from tv; insert_time-----------------20130811 09:39:40  execution plan----------------------------------------------------------plan hash value: 1723968289 --------------------------------------------------------------------------| id | operation | name | rows | bytes | cost (%cpu)| time |--------------------------------------------------------------------------| 0 | select statement | | 3 | 6087 | 102 (0)| 00:00:01 ||* 1 | table access full| tv | 3 | 6087 | 102 (0)| 00:00:01 |-------------------------------------------------------------------------- predicate information (identified by operation id):---------------------------------------------------  1 - filter(t.ora_archive_state='0' and (t.valid_time_start is null or internal_function(t.valid_time_start)timestamp' 2013-08-11 09:39:50.000000000'))  statistics---------------------------------------------------------- 35 recursive calls 6 db block gets 398 consistent gets 0 physical reads 0 redo size 550 bytes sent via sql*net to client 543 bytes received via sql*net from client 2 sql*net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
结论:数据库内归档是一个oracle利用隐藏字段实现的非常简单的功能,但是数据架构人员在规划的时候一定要考虑性能因素。
share/save
related posts:
oracle 11g new feature – virtual column how to use dbms_advanced_rewrite in oracle 10g 【oracle database 12c new feature】how to learn oracle (12c new feature) from error
其它类似信息

推荐信息