今天看Concepts第四章 分区时
其中有一个特性:
-
Increased availability
The unavailability of a partition does not entail the unavailability of the object. The query optimizer automatically removes unreferenced partitions from the query planso queries are not affected when the partitions are unavailable.
经过实验以后,这段文本的译文变成如下:
一个分区的不可用,不会导致整个对象的不可用。比如查询某个表,当返回的数据(通过where条件判断)不可能会存在一个分区,则CBO不会对这个分区访问,而当这个分区损坏时,因为CBO生成的执行计划中并没有去访问这个分区,那么语句看起来和执行起来都是正常的。
实验如下:
过程简述:1、创建分区表,且放入不同表空间。2、将其中一个表空间offline,造成分区不可用的现象。3、分别使用不同的where条件查询
一、创建分区表,每个分区都插入数据:
SQL> create table test_part(no number) partition by range(no)(
partition part1 values less than (5) tablespace test,
partition part2 values less than (10),
partition part3 values less than (maxvalue));
Table created.
SQL> insert into test_part values(1);
1 row created.
SQL> insert into test_part values(9);
1 row created.
SQL> insert into test_part values(11);
1 row created.
SQL> commit;
查看一下:
SQL> select segment_name,partition_name from user_segments where segment_name='TEST_PART';
SEGMENT_NAME PARTITION_NAME
-------------------- ------------------------------
TEST_PART PART1
TEST_PART PART2
TEST_PART PART3
二、将test表空间offline
SQL> alter tablespace test offline;
Tablespace altered
三、使用不同sql访问test_part表
1、请求的数据包含 不可用 的表分区时 结论:会报错
SQL> select * from test_part; --数据包含了第一个表分区 <5的值
select * from test_part
*
ERROR at line 1:
ORA-00376: file 6 cannot be read at this time
ORA-01110: data file 6: '/u01/app/oracle/oradata/orcl/test.dbf'
执行计划如下,可以看到从 第一个分区扫描到第三个分区
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3584404593
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 246 | 3198 | 2 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE ALL| | 246 | 3198 | 2 (0)| 00:00:01 | 1 | 3 | --注意这里 1 - 3
| 2 | TABLE ACCESS FULL | TEST_PART | 246 | 3198 | 2 (0)| 00:00:01 | 1 | 3 | --注意这里 1 - 3
-------------------------------------------------------------------------------------------------
2、请求的数据不包含 不可用 分区时
SQL> select * from test_part where no>5; ---数据正常查出了
NO
----------
9
11
执行计划如下,可以看到,这里CBO自动规避掉 没有数据返回的第一个损坏分区
所以 第一个分区损坏了,对这个sql没有任何影响。
注:第一个分区的定义是no<5。而这里的where条件为no>5
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 4294476422
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 39 | 18 (0)| 00:00:01 | | |
| 1 | PARTITION RANGE ITERATOR| | 3 | 39 | 18 (0)| 00:00:01 | 2 | 3 | --注意这里 2 - 3
|* 2 | TABLE ACCESS FULL | TEST_PART | 3 | 39 | 18 (0)| 00:00:01 | 2 | 3 | --注意这里 2 - 3
------------------------------------------------------------------------------------------------------
因为这里是分区1 失效了,但是这个执行计划并没有访问分区1,那么这里执行起来是很正常的!不会报错
勤学如春起之苗,不见其增日有所长。辍学如磨刀之石,不见其损日有所亏