前兩天碰到一個問題,在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 test
where 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 test
where 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="http://www.2cto.com/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 閉源”對待某個問題的一種態度。