聊聊Oracle 11g中的Reference Partition(下)

简介:   上篇中,我们介绍了Reference Partition的创建、使用和原理。本篇将从性能和管理两个角度,讨论Reference Partition的作用。

 

上篇中,我们介绍了Reference Partition的创建、使用和原理。本篇将从性能和管理两个角度,讨论Reference Partition的作用。

 

4Reference Partition与执行计划

 

直观上看,Reference Partition应当是有益于执行计划的。主子表之间通过外键进行关联,最常用的业务场景就是借助外键列进行关联查询。如果主表记录是在一个或者几个分区上,那么子表对应的记录应该是在一个或者几个分区上。

这样,就从定义层面减少了数据访问量。下面通过一系列的实验进行证明。

 

 

SQL> explain plan for select * from t_master a, t_detail b where a.object_id=b.master_id;

 

Explained

 

SQL> select * from table(dbms_xplan.display);

 

PLAN_TABLE_OUTPUT

--------------------------------------------------------------------------------

Plan hash value: 2684484261

--------------------------------------------------------------------------------

| Id  | Operation            | Name     | Rows  | Bytes |TempSpc| Cost (%CPU)| T

--------------------------------------------------------------------------------

|   0 | SELECT STATEMENT     |          |   238K|    18M|       |   642   (3)| 0

|   1 |  PARTITION LIST ALL  |          |   238K|    18M|       |   642   (3)| 0

|   2 |   MERGE JOIN         |          |   238K|    18M|       |   642   (3)| 0

|   3 |    SORT JOIN         |          |   120K|  4936K|    12M|   222   (3)| 0

|   4 |     TABLE ACCESS FULL| T_MASTER |   120K|  4936K|       |   217   (1)| 0

|*  5 |    SORT JOIN         |          |   240K|  9403K|    23M|   419   (3)| 0

|   6 |     TABLE ACCESS FULL| T_DETAIL |   240K|  9403K|       |   412   (1)| 0

--------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   5 - access("A"."OBJECT_ID"="B"."MASTER_ID")

       filter("A"."OBJECT_ID"="B"."MASTER_ID")

 

19 rows selected

 

 

第一个语句我们没有加入分区条件,访问了所有的分区,路径中出现了“Partition List All”语句。注意:分区表的全表扫描,成本要大于扫描一张大表。分区表最大意义在于加入分区条件的查询语句。

第二个语句,我们加入主表的owner分区条件。

 

 

SQL> explain plan for select * from t_master a, t_detail b where a.object_id=b.master_id and owner='SCOTT';

 

Explained

 

SQL> select * from table(dbms_xplan.display);

 

PLAN_TABLE_OUTPUT

--------------------------------------------------------------------------------

Plan hash value: 3648887064

--------------------------------------------------------------------------------

| Id  | Operation             | Name     | Rows  | Bytes | Cost (%CPU)| Time

--------------------------------------------------------------------------------

|   0 | SELECT STATEMENT      |          |  2600 |   198K|   495   (1)| 00:00:06

|   1 |  PARTITION LIST SINGLE|          |  2600 |   198K|   495   (1)| 00:00:06

|*  2 |   HASH JOIN           |          |  2600 |   198K|   495   (1)| 00:00:06

|*  3 |    TABLE ACCESS FULL  | T_MASTER |  1312 | 49856 |    82   (0)| 00:00:01

|   4 |    TABLE ACCESS FULL  | T_DETAIL |   240K|  9403K|   412   (1)| 00:00:05

--------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   2 - access("A"."OBJECT_ID"="B"."MASTER_ID")

   3 - filter("OWNER"='SCOTT')

 

17 rows selected

 

 

注意:该语句中,利用owner条件,扫描的重点集中在t_master的单一分区,进行了“Partition List Single”操作,扫描之后的结果,在子表中“一定对应”一个子表分区。所以对T_Detail的扫描也是Partition List Single

如果子表没有分区,我们进行一下实验。

 

 

SQL> create table t_normal as select * from t_detail;

Table created

 

SQL> commit;

Commit complete

 

SQL> exec dbms_stats.gather_table_stats(user,'T_NORMAL',cascade => true);

PL/SQL procedure successfully completed

 

 

查看执行计划:

 

 

SQL> explain plan for select * from t_master a, t_normal b where a.object_id=b.master_id and owner='SCOTT';

 

Explained

 

SQL> select * from table(dbms_xplan.display);

 

PLAN_TABLE_OUTPUT

--------------------------------------------------------------------------------

Plan hash value: 1706510341

--------------------------------------------------------------------------------

| Id  | Operation              | Name     | Rows  | Bytes | Cost (%CPU)| Time

--------------------------------------------------------------------------------

|   0 | SELECT STATEMENT       |          |  2600 |   198K|   494   (1)| 00:00:0

|*  1 |  HASH JOIN             |          |  2600 |   198K|   494   (1)| 00:00:0

|   2 |   PARTITION LIST SINGLE|          |  1312 | 49856 |    82   (0)| 00:00:0

|*  3 |    TABLE ACCESS FULL   | T_MASTER |  1312 | 49856 |    82   (0)| 00:00:0

|   4 |   TABLE ACCESS FULL    | T_NORMAL |   240K|  9403K|   411   (1)| 00:00:0

--------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   1 - access("A"."OBJECT_ID"="B"."MASTER_ID")

   3 - filter("OWNER"='SCOTT')

 

17 rows selected

 

 

请注意对T_NORMAL表的“Table Access Full”操作,它并没有涉及到分区。也就是说,从t_master中筛选到的记录owner=SCOTT’到T_NORMAL中,进行的是全表扫描操作。

从现在执行计划,我们的确看到了Reference Partition在执行计划上的优势。那么,还有无提升空间?

余地就是外键索引!为了避免大规模并发过程中出现死锁的情况,外键列是要求加索引的。笔者如果在Reference Partition的情况下,加入索引,会如何呢?

 

 

SQL> create index idx_t_detail_mas on t_detail(master_id) local;

Index created

 

SQL> exec dbms_stats.gather_table_stats(user,'T_DETAIL',cascade => true);

PL/SQL procedure successfully completed

 

 

执行计划:

 

 

SQL> explain plan for select * from t_master a, t_detail b where a.object_id=b.master_id and owner='SCOTT';

 

Explained

 

SQL> select * from table(dbms_xplan.display);

 

PLAN_TABLE_OUTPUT

---------------------------------------

Plan hash value: 3648887064

------------------------------------------------

| Id  | Operation             | Name     | Rows  | Bytes | Cost (%CPU)| Time

-----------------------------------------------------------

|   0 | SELECT STATEMENT      |          |  2600 |   198K|   495   (1)| 00:00:06

|   1 |  PARTITION LIST SINGLE|          |  2600 |   198K|   495   (1)| 00:00:06

|*  2 |   HASH JOIN           |          |  2600 |   198K|   495   (1)| 00:00:06

|*  3 |    TABLE ACCESS FULL  | T_MASTER |  1312 | 49856 |    82   (0)| 00:00:01

|   4 |    TABLE ACCESS FULL  | T_DETAIL |   240K|  9403K|   412   (1)| 00:00:05

--------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   2 - access("A"."OBJECT_ID"="B"."MASTER_ID")

   3 - filter("OWNER"='SCOTT')

 

17 rows selected

 

 

执行计划没有改变,说明在CBO计算过程中,索引策略被分区策略成本值“打败”了。这个在很多没有特殊调优的分区表语句中十分常见。

笔者尝试了一下直方图路径,看是否可以生成更好的执行计划。

 

 

SQL> exec dbms_stats.gather_table_stats(user,'T_MASTER',cascade => true,method_opt => 'for all columns size auto');

 

PL/SQL procedure successfully completed

 

SQL> exec dbms_stats.gather_table_stats(user,'T_DETAIL',cascade => true,method_opt => 'for all columns size auto');

 

PL/SQL procedure successfully completed

 

 

执行计划情况:

 

 

SQL> explain plan for select * from t_master a, t_detail b where a.object_id=b.master_id and owner='SCOTT';

 

Explained

 

SQL> select * from table(dbms_xplan.display);

 

PLAN_TABLE_OUTPUT

--------------------------------------------------

Plan hash value: 2296204501

------------------------------------------------------------------------------------------------------------------------

| Id  | Operation                           | Name             | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |

------------------------------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT                    |                  |    35 |  2730 |   136   (0)| 00:00:02 |       |       |

|   1 |  PARTITION LIST SINGLE              |                  |    35 |  2730 |   136   (0)| 00:00:02 |   KEY |   KEY |

|   2 |   NESTED LOOPS                      |                  |    35 |  2730 |   136   (0)| 00:00:02 |       |       |

|   3 |    NESTED LOOPS                     |                  |    36 |  2730 |   136   (0)| 00:00:02 |       |       |

|*  4 |     TABLE ACCESS FULL               | T_MASTER         |    18 |   684 |    82   (0)| 00:00:01 |     3 |     3 |

|*  5 |     INDEX RANGE SCAN                | IDX_T_DETAIL_MAS |     2 |       |     1   (0)| 00:00:01 |   KEY |   KEY |

|   6 |    TABLE ACCESS BY LOCAL INDEX ROWID| T_DETAIL         |     2 |    80 |     3   (0)| 00:00:01 |   KEY |   KEY |

------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

   4 - filter("OWNER"='SCOTT')

   5 - access("A"."OBJECT_ID"="B"."MASTER_ID")

 

19 rows selected

 

 

索引路径走到,执行计划成本下降到136

说明:在使用Reference Partition的情况下,主子表外键连接的语句的确可以得到一定程度的性能提升。更容易生成更好的执行计划。

 

5、管理角度

 

从管理角度看,Reference Partition将主子表记录“牢牢”的绑定在一起,对应的分区也紧密关系在一起。

如果我们对主表分区进行操作处理,对应的子表分区也会进行自动的操作。下面我们操作t_master对象分区。

我们将主表分区p1摘除,仅从主从表记录关系看,数据库应该让先删除子表记录。

 

 

SQL> alter table t_master drop partition p1;

Table altered

 

 

摘除成功,说明Reference Partition连带影响子表分区被删除。

 

 

SQL> col num_rows for a10;

SQL> col high_value for a10;

SQL> col partition_name for a10;

SQL> col table_name for a10;

SQL> select table_name, partition_name, high_value,num_rows from dba_tab_partitions where table_owner='SYS' and table_name in

 

('T_DETAIL','T_MASTER');

 

TABLE_NAME PARTITION_ HIGH_VALUE   NUM_ROWS

---------- ---------- ---------- ----------

T_DETAIL   P0                         67992

T_DETAIL   P3                         97096

T_MASTER   P0         'PUBLIC'        33996

T_MASTER   P3         default         48548

 

 

主子表分区联动处理。

 

6、结论

 

Reference PartitionOracle 11g推出的一个重要的新特性。借助该特性,我们从定义分区表、管理分区表和使用分区表等多个方面,都可以得到很多好处。


目录
相关文章
|
4月前
|
Oracle 关系型数据库 数据库
使用docker安装配置oracle 11g
使用docker安装配置oracle 11g
|
6月前
|
Oracle 关系型数据库 数据库
Oracle 11G常见性能诊断报告(AWR/ADDM/ASH)收集
Oracle 11G常见性能诊断报告(AWR/ADDM/ASH)收集
|
1月前
|
存储 Oracle 关系型数据库
手把手教你安装Oracle——以oracle 11g为例
手把手教你安装Oracle——以oracle 11g为例
手把手教你安装Oracle——以oracle 11g为例
|
4月前
|
SQL Oracle 关系型数据库
docker 方式安装ORACLE 11g
docker 方式安装ORACLE 11g
199 4
|
5月前
|
Oracle 关系型数据库 数据库
在Flink CDC中,使用Oracle 11g数据库的NUMBER类型作为主键
在Flink CDC中,使用Oracle 11g数据库的NUMBER类型作为主键
48 1
|
5月前
|
SQL Oracle 安全
window下Oracle 11G安装文档
window下Oracle 11G安装文档
|
7月前
|
Oracle 关系型数据库
Oracle 11g和12c的主要区别
Oracle 11g和12c的主要区别
|
9月前
|
Oracle 关系型数据库 数据库连接
Oracle 11g安装配置完美教程 - Windows(下)
Oracle 11g安装配置完美教程 - Windows(下)
154 0
|
9月前
|
SQL Oracle 安全
Oracle 11g安装配置完美教程 - Windows(上)
Oracle 11g安装配置完美教程 - Windows
748 0
|
安全 Oracle Java