我们继续来讨论分区的动机。分区技术Partition已经脱离了原有的性能出发点,而更多的关注海量数据管理问题。本篇会集中在管理中的数据转移、生命周期管理和备份几个角度。
7、数据转移
海量数据一个很常见的模式就是ETL动作。数据分析的基础就是一系列的group汇总,针对交易业务数据的汇总动作。从SQL角度看,group by是一个很消耗资源的动作。而且,group by天然是没有划分这个动作的。
比如,我们基础交易数据t_part,希望将其汇总为t_part_summary,根据owner汇总,以object_id进行加总。
SQL> create table t_part_sum as select owner, sum(object_id) sum_value from t_part where
1=0 group by owner;
Table created
SQL> select count(*) from t_part_sum;
COUNT(*)
----------
0
SQL> desc t_part_sum;
Name Type Nullable Default Comments
--------- ------------ -------- ------- --------
OWNER VARCHAR2(30) Y
SUM_VALUE NUMBER Y
最直接、最传统的做法就是简单的进行group by之后insert。
SQL> set timing on;
SQL> insert into t_part_sum select owner, sum(object_id) from t_part group by owner;
32 rows inserted
Executed in 0.218 seconds
这种方式应该说很简单,一些熟悉Oracle的朋友可能会选择加入append和nologging进行优化。这种手法在数据量少的时候,的确是不错的选择。但是,凡事均有一个适应范围,这种方法潜在两个问题。
首先,直接的insert动作,会产生大量的undo和redo数据,而且是瞬间性的。这个在生产环境下是可能会引起一些性能问题。一般朋友的处理方法就是使用append和nologging,来减少redo数据的生成。此外还可以增大redo log member体积,缓解压力。
第二个问题在于事务的规模。我们一次性的生成数据表全部数据,底层业务数据在group by的全过程中是要一次性读入并且汇总计算。这个操作时间是很难控制的,同时group by动作的调整是和PGA调优、Temp空间调优紧密相关。我们经常遇到的一个场景,就是长时间的group by动作,最后以Temp空间耗尽告终。
笔者有一个论点:SQL语句最大的迷惑之处在于需要开发人员意识到数据量的问题。不同的操作对象选择的操作方法是不同的。
针对第一个问题,也许直接的insert+append+nologging可以暂时满足非功能性需要。针对第二个问题,也许目前系统性能Temp空间可以支持。但是,随着底层业务数据的膨胀,这种状况能持续多久?
解决的方法在于数据操作的平缓化。将一个海量的、不可知总量的操作转化为一系列可控的操作系列是我们处理海量数据的最常规思路。
结合Partition,我们可以实现的更好。
我们首先还是创建汇总表,但是这次的汇总表是一个分区表。
SQL> drop table t_part_sum;
Table dropped
Executed in 1.248 seconds
SQL> create table t_part_summary
2 partition by list (owner)
3 (
4 partition p0 values ('SYS'),
5 partition p1 values ('PUBLIC'),
6 partition p2 values (default)
7 )
8 as select owner, object_type, sum(object_id) sum_value
9 from t_part
10 where 1=0
11 group by owner, object_type;
Table created
Executed in 0.156 seconds
创建出一个临时表,按照分区的方式进行数据部分汇总动作。注意:这边一次性的操作只是在一个分区里面进行,带来的负载是相对小。
SQL> create table t_part_sum_temp as select owner, object_type, sum(object_id) sum_value from t_part where owner='SYS' group by owner, object_type;
Table created
Executed in 0.093 seconds
最后,通过exchange方式进行替换。
SQL> alter table t_part_summary exchange partition p0 with table t_part_sum_temp including indexes;
Table altered
Executed in 0.156 seconds
SQL> select count(*) from t_part_summary;
COUNT(*)
----------
40
Executed in 0.016 seconds
SQL> select count(*) from t_part_sum_temp;
COUNT(*)
----------
0
Executed in 0.031 seconds
将一个insert+group by转化为一系列的group by和exchange partition,是可以适应海量数据维护工作的。
8、数据生命周期
这种管理思路的基础在于一个假设:数据是有生命周期的,是有明显的活性。对大部分的OLTP系统而言,这种说法是有道理的。
一个系统的数据刚刚进入系统中,其活性是非常强的。在很短的时间内,往往要经过系统最复杂的交易逻辑、最严格的运行算法,最后进入报表模块形成交易汇总。这部分对于系统而言,性能是至关重要的。所有的设计都是围绕着这个环节。
当数据经过这个阶段,进入沉积期之后,操作动作就会快速减少。很多时候,系统有没有将这个数据删除,完全不影响系统工作了。这个时期,这部分系统的性能要求是不高的。
我们的数据性能中,很大一个因素在于IO。IO直接是从成本决定的。如果我们有快的IO,还有慢的IO,就可以利用分区技术将不同活性的数据分散在不同的存储设备上,从而获得最优均衡。
SQL> select partition_name, tablespace_name from dba_tab_partitions where
table_owner='SYS' and table_name='T_PART';
PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
P1 SYSTEM
P2 SYSTEM
P3 SYSTEM
Executed in 0.062 seconds
SQL> alter table t_part move partition p3 tablespace users update global indexes;
Table altered
Executed in 0.28 seconds
SQL> select partition_name, tablespace_name from dba_tab_partitions where
table_owner='SYS' and table_name='T_PART';
PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------
P1 SYSTEM
P2 SYSTEM
P3 USERS
Executed in 0.078 seconds
9、数据备份
Partition能够优化备份工作。这点的源头在于不同数据活性的事实。如果一个分区数据没有活性,不会发生变化了。一种好的做法是将其单独放在一个表空间里面,设置表空间为只读read only。
SQL> alter tablespace users read only;
Tablespace altered
Executed in 0.156 seconds
一旦表空间被设置为read only,从备份角度是存在优化空间的。Oracle进行备份识别的时候,只会备份这个表空间一次。在第二次进行备份的时候,这个表空间就不会进行备份了。
10、结论
Partition是Oracle的一项重要技术,也是我们常见的优化手段。使用分区,首先要明确出使用的目的。在实践中,分区可能会成为双刃剑。分区策略的选择,性能和管理,是需要设计人员明确的重要取舍。如果更关注性能,而且需求层面有很强烈的数据访问规律性,那么可以使用分区。如果更关注管理,数据活跃性是否明显是我们考量的方面。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/30373263/viewspace-2122093/ ,如需转载,请注明出处,否则将追究法律责任。