虚位以待(AD)
虚位以待(AD)
首页 > 数据库 > Oracle数据库 > EDB和Oracle在分区剪裁实践上的一点差别

EDB和Oracle在分区剪裁实践上的一点差别
类别:Oracle数据库   作者:码皇   来源:bisal的专栏     点击:

前两天碰到一个问题,在EDB数据库中创建的一张分区表,需要使用分区本地索引和分区剪裁,但查看执行计划发现没能用到分区剪裁的功能。创建分区表:CREATE TABLE test( id bigint NOT NULL, ba

前两天碰到一个问题,在EDB数据库中创建的一张分区表,需要使用分区本地索引和分区剪裁,但查看执行计划发现没能用到分区剪裁的功能。

创建分区表:

    CREATE TABLE test( id bigint NOT NULL, bag_id bigint, bp_airline_code character varying(3), bp_flight character varying(5), bp_flight_suffix character varying(2), bp_flight_date timestamp with time zone, CONSTRAINT pk_test PRIMARY KEY (id))partition by range(bp_flight_date)( partition part_20151101 VALUES LESS THAN('2015-NOV-02'), partition part_20151102 VALUES LESS THAN('2015-NOV-03'), partition part_20151103 VALUES LESS THAN('2015-NOV-04'));

创建主表和三个分区的本地索引:

    CREATE INDEX test_idx_01 ON test (bag_id, bp_airline_code, bp_flight, bp_flight_suffix);
    CREATE INDEX test_part_20151101_idx ON test_part_20151101 (bag_id, bp_airline_code, bp_flight, bp_flight_suffix);
    CREATE INDEX test_part_20151102_idx ON test_part_20151102 (bag_id, bp_airline_code, bp_flight, bp_flight_suffix);
    CREATE INDEX test_part_20151103_idx ON test_part_20151103 (bag_id, bp_airline_code, bp_flight, bp_flight_suffix);

执行以下带有分区键的查询语句,:

    explain select * from testwhere bp_flight_date=to_date('2015-11-01', 'yyyy-mm-dd') and bag_id = 1

发现并没有使用到分区剪裁:
这里写图片描述

有点疑惑,明明用了分区键作为查询条件,为什么此处是扫描了所有分区?

分析
其实这个问题说简单也简单,说麻烦也麻烦,主要还是细节和原理的理解。
上例中使用的分区规则是:

    partition by range(bp_flight_date)( partition part_20151101 VALUES LESS THAN('2015-NOV-02')...

以bp_flight_date日期字段作为分区键,条件是LESS THAN(‘2015-NOV-02’)。但执行的查询语句条件是:

    where bp_flight_date=to_date('2015-11-01', 'yyyy-mm-dd') and bag_id = 1

对日期值是使用了to_date函数,并不是像分区规则中的“字符串”格式,有理由怀疑是因为两者不统一,由于某些RULE导致未能用到分区剪裁的功能。

接下来按照猜想改下查询条件:

    explain select * from testwhere bp_flight_date='2015-11-01', 'yyyy-mm-dd' and bag_id = 1

查看执行计划:
这里写图片描述vcHLt9bH+Lz0ssO1xMS/tcShozwvcD4KCjxwPtauy/nS1NPQyc/D5tXi0KnOyszio6y/ycTcu7nKx9S009pPcmFjbGW1xNK70KnLvM6so6zU2k9yYWNsZaOs0uLKtrWx1tC9q8jVxtrX1rbO1/fOqrLp0a/M9bz+vs3TprjDyrnTw3RvX2RhdGUoKdXiwOC1xLqvyv08L3A+Cgo8cD66zcnPw+bP4M2stcSx7b3hubnU2k9yYWNsZdbQtcTKtc/Wo7ogPGJyPgo8aW1nIHNyYz0="/uploadfile/Collfiles/20151130/201511300932566.png" alt="这里写图片描述" title="">

这里写图片描述
这里看到执行计划显示还是用到了分区特性,并没有执行全表扫描,其中Pstart和Pstop显示的是KEY,表示是基于函数值的分区键。

那么像EDB这样创建一个不用to_date函数的分区表:
这里写图片描述Oracle的一点不同。

总结
1. EDB中分区键是日期字段,VALUES LESS THAN(‘2015-11-01’)可以使用字符串格式,但Oracle则会报ORA-01861的错误,不支持这种创建方式。
2. EDB对使用分区键的查询语句,如果日期条件的格式和分区规则中不同,例如分区规则是’2015-NOV-01’或’2015-11-01’,但查询条件使用to_date(‘2015-11-01’,’yyyy-mm-dd’),则不会用到分区剪裁的特性,而是扫描所有分区。对于Oracle,在创建分区规则时就已经做了严格限制,因此不存在日期条件的格式和分区规则中不一致的情况。这两种方式说不上孰好孰坏,EDB是更自由,但需要人为注意书写的正确,Oracle则是严谨,好处是避免了人为使用出错的可能,间接上可能也反映出了“社区 VS 商业”、“开源 VS 闭源”对待某个问题的一种态度。

相关热词搜索:
上一篇:Oracle索引重建
下一篇:oracle 自增长序列