Oracle分區表之分區范圍掃描(PARTITION RANGE ITERATOR)與位圖范圍掃描(BITMAP INDEX RANGE SCAN)


一.前言:

一開始分區表和位圖索引怎么會掛鈎呢?可能現實就是這么的不期而遇;比如說一張表的字段是年月日—‘yyyy-mm-dd’,重復率高吧,適合建位圖索引吧,而且這張表數據量也不小,也適合轉換成分區表吧!下面我來比較一下分區表和分區字段位圖索引的性能!

 

二.實驗

生產上的表結構以及索引:

create table LOT_WIN_RESULT_DETAIL
(
id INTEGER not null,
rpt_date DATE,
sys_game_level_code_id INTEGER,
game_desc VARCHAR2(50),
periods_no VARCHAR2(50),
start_tt VARCHAR2(10),
end_tt VARCHAR2(10),
ok_dtt VARCHAR2(10),
ok_ind CHAR(1),
open_code VARCHAR2(500),
remark VARCHAR2(50),
json_result VARCHAR2(4000),
getdata_dtt TIMESTAMP(6),
last_modfiy_user_id INTEGER,
last_modfiy_user_name VARCHAR2(50),
last_modfiy_dtt TIMESTAMP(6),
platform_ident VARCHAR2(45)
)
tablespace NB_TBS_YOBET
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 24M
next 1M
minextents 1
maxextents unlimited
);

-- Create/Recreate indexes
create bitmap index IX1_LOT_WIN_DTL on LOT_WIN_RESULT_DETAIL (PLATFORM_IDENT) tablespace NB_INX_TBS_YOBET
;
create index IX2_LOT_WIN_DTL on LOT_WIN_RESULT_DETAIL (SYS_GAME_LEVEL_CODE_ID, PERIODS_NO) tablespace NB_INX_TBS_YOBET
;
create bitmap index IX4_LOT_WIN_DTL on LOT_WIN_RESULT_DETAIL (RPT_DATE) tablespace NB_INX_TBS_YOBET
;
create index LX_LOT_WIN_RESULT_DETAIL_TIME on LOT_WIN_RESULT_DETAIL (GETDATA_DTT) tablespace NB_INX_TBS_YOBET
;
-- Create/Recreate primary, unique and foreign key constraints
alter table LOT_WIN_RESULT_DETAIL add constraint PK_LOT_WIN_RESULT_DETAIL primary key (ID) using index tablespace NB_TBS_YOBET
;

 模擬建一張一模一樣的分區表( LOT_WIN_RESULT_DETAIL_part),以rpt_date時間字段分區,且把數據量插入過來:

create table LOT_WIN_RESULT_DETAIL_part
(
id INTEGER not null,
rpt_date DATE,
sys_game_level_code_id INTEGER,
game_desc VARCHAR2(50),
periods_no VARCHAR2(50),
start_tt VARCHAR2(10),
end_tt VARCHAR2(10),
ok_dtt VARCHAR2(10),
ok_ind CHAR(1),
open_code VARCHAR2(500),
remark VARCHAR2(50),
json_result VARCHAR2(4000),
getdata_dtt TIMESTAMP(6),
last_modfiy_user_id INTEGER,
last_modfiy_user_name VARCHAR2(50),
last_modfiy_dtt TIMESTAMP(6),
platform_ident VARCHAR2(45)
)PARTITION BY RANGE(RPT_DATE) INTERVAL (NUMTODSINTERVAL(1, 'DAY'))
(
PARTITION RPT_DATE_20191218 VALUES LESS THAN(TO_DATE('2019-12-19', 'YYYY-MM-DD'))
) tablespace NB_TBS_YOBET ;


create bitmap index IX1 on LOT_WIN_RESULT_DETAIL_part (PLATFORM_IDENT)
local tablespace NB_INX_TBS_YOBET
;
create index IX2 on LOT_WIN_RESULT_DETAIL_part (SYS_GAME_LEVEL_CODE_ID, PERIODS_NO)
local tablespace NB_INX_TBS_YOBET
;

create index LX3 on LOT_WIN_RESULT_DETAIL_part (GETDATA_DTT) lcoal tablespace NB_INX_TBS_YOBET
;
-- Create/Recreate primary, unique and foreign key constraints
alter table LOT_WIN_RESULT_DETAIL_part
add constraint PK_LOT_WIN_RESULT_DETAIL_p primary key (ID)
using index
tablespace NB_TBS_YOBET
;

insert into LOT_WIN_RESULT_DETAIL_part select * from LOT_WIN_RESULT_DETAIL;

數據庫都是89萬。

BEGIN
DBMS_STATS.GATHER_TABLE_STATS( OWNNAME => 'RACTTFC',
TABNAME => 'LOT_WIN_RESULT_DETAIL_part',
CASCADE => TRUE);
END;
/

 

BEGIN
DBMS_STATS.GATHER_TABLE_STATS( OWNNAME => 'RACTTFC',
TABNAME => 'LOT_WIN_RESULT_DETAIL_part',
CASCADE => TRUE);
END;
/

 

2.1 時間分區字段范圍查詢   

 

語句如下:

select rpt_date,
periods_no,
open_code,
json_result,
remark,
ok_dtt as start_tt,
GAME_DESC,
rownums
from (select rpt_date,
periods_no,
a.open_code,
a.json_result,
a.remark,
a.ok_dtt,
a.GAME_DESC,
ROW_NUMBER() OVER(ORDER BY to_number(periods_no) desc) as rownums
from lot_win_result_detail a
where rpt_date >=
to_date('2019-12-23 00:00:00', 'yyyy-mm-dd HH24:mi:ss')
and rpt_date <=
to_date('2019-12-24 23:59:59', 'yyyy-mm-dd HH24:mi:ss')
and sys_game_level_code_id = 5827
and ok_ind >= '1'
and PLATFORM_IDENT = 'af') a
where rownums <= 10
order by to_number(periods_no) desc;

執行計划如下:

 

 

 

采用了bitmap 索引范圍掃描,CPU成本3652;

 

select rpt_date,
periods_no,
open_code,
json_result,
remark,
ok_dtt as start_tt,
GAME_DESC,
rownums
from (select rpt_date,
periods_no,
a.open_code,
a.json_result,
a.remark,
a.ok_dtt,
a.GAME_DESC,
ROW_NUMBER() OVER(ORDER BY to_number(periods_no) desc) as rownums
from lot_win_result_detail_part a
where rpt_date >=
to_date('2019-12-23 00:00:00', 'yyyy-mm-dd HH24:mi:ss')
and rpt_date <=
to_date('2019-12-24 23:59:59', 'yyyy-mm-dd HH24:mi:ss')
and sys_game_level_code_id = 5827
and ok_ind >= '1'
and PLATFORM_IDENT = 'af') a
where rownums <= 10
order by to_number(periods_no) desc;

 

 

基於分區過略,且基數2881比2671大,最終消耗的成本1442比3652低的多,且最開始進行的分區表索引范圍掃描成本105比非分區表的539 小的多。

 

2.2時間分區字段等值

select rpt_date,
periods_no,
open_code,
json_result,
remark,
ok_dtt as start_tt,
GAME_DESC,
rownums
from (select rpt_date,
periods_no,
a.open_code,
a.json_result,
a.remark,
a.ok_dtt,
a.GAME_DESC,
ROW_NUMBER() OVER(ORDER BY to_number(periods_no) desc) as rownums
from lot_win_result_detail a
where rpt_date =
to_date('2019-12-23', 'yyyy-mm-dd')
and sys_game_level_code_id = 5827

and ok_ind >= '1'
and PLATFORM_IDENT = 'af') a
where rownums <= 10
order by to_number(periods_no) desc;

 

 

 單個值的查詢的時候,bitmap沒有進行范圍掃描,進行了單個等值查詢,通過索引范圍掃描,然后再通過bimap索引轉換成ROWID,最后通過又通過bitmap回表,CPU 耗費成本2515;

同理,換成分區表:

select rpt_date,
periods_no,
open_code,
json_result,
remark,
ok_dtt as start_tt,
GAME_DESC,
rownums
from (select rpt_date,
periods_no,
a.open_code,
a.json_result,
a.remark,
a.ok_dtt,
a.GAME_DESC,
ROW_NUMBER() OVER(ORDER BY to_number(periods_no) desc) as rownums
from lot_win_result_detail_part a
where rpt_date =
to_date('2019-12-23', 'yyyy-mm-dd')
and sys_game_level_code_id = 5827

and ok_ind >= '1'
and PLATFORM_IDENT = 'af') a
where rownums <= 10
order by to_number(periods_no) desc;

 

 

整個執行計划是走的單個分區,通過索引范圍掃描,然后再通過bimap索引轉換成ROWID,最后通過又通過bitmap回表,CPU 耗費成本763,遠遠小於2515,且單個的索引掃描51 遠遠小於上述的551索引范圍掃描(這個是分區表利用本地索引的優勢);

整個兩次對比結果bitmap無論是在范圍查詢還是單個的等值查詢都是完敗。

 

2.3 分區表分區索引變成全局索引

drop index IX222;
create index IX222 on LOT_WIN_RESULT_DETAIL_part (SYS_GAME_LEVEL_CODE_ID, PERIODS_NO) tablespace NB_INX_TBS_YOBET;

BEGIN 
DBMS_STATS.GATHER_TABLE_STATS( OWNNAME => 'RACTTFC', 
TABNAME => 'LOT_WIN_RESULT_DETAIL_part', 
CASCADE => TRUE); 
END; 
/

select rpt_date,
periods_no,
open_code,
json_result,
remark,
ok_dtt as start_tt,
GAME_DESC,
rownums
from (select rpt_date,
periods_no,
a.open_code,
a.json_result,
a.remark,
a.ok_dtt,
a.GAME_DESC,
ROW_NUMBER() OVER(ORDER BY to_number(periods_no) desc) as rownums
from lot_win_result_detail a
where rpt_date >=
to_date('2019-12-23 00:00:00', 'yyyy-mm-dd HH24:mi:ss')
and rpt_date <=
to_date('2019-12-24 23:59:59', 'yyyy-mm-dd HH24:mi:ss')
and sys_game_level_code_id = 5827
and ok_ind >= '1'
and PLATFORM_IDENT = 'af') a
where rownums <= 10
order by to_number(periods_no) desc;

 

 分區范圍內的全表掃描,並沒有用到新建的哪個索引,CPU成本4587,遠高於bitmap的3652;

單個值的查詢:

select rpt_date,
periods_no,
open_code,
json_result,
remark,
ok_dtt as start_tt,
GAME_DESC,
rownums
from (select rpt_date,
periods_no,
a.open_code,
a.json_result,
a.remark,
a.ok_dtt,
a.GAME_DESC,
ROW_NUMBER() OVER(ORDER BY to_number(periods_no) desc) as rownums
from lot_win_result_detail_part a
where rpt_date =date'2019-12-23'
and sys_game_level_code_id = 5827
and ok_ind >= '1'
and PLATFORM_IDENT = 'af') a
where rownums <= 10
order by to_number(periods_no) desc;

 

 同理一樣的全局索引沒有使用,2193和2515是一個數量級的,差距不是很明顯。

 

三.結論

綜上所述,bitmap 在進行等值與以及范圍查詢的時候,整個執行過程大致一樣,但是,主要是分區表能夠在分區范圍內利用本地索引進行掃描(全局索引幾乎是幾個量級),非分區表沒有這種優勢;

索引在rang范圍查詢字段方面。建議使用分區加local 索引,會造成BITMAP INDEX RANGE SCAN並沒有PARTITION RANGE ITERATOR 加local 索引高效,值得注意的是OLTP在線環境如果是DML比較頻繁,不會建議使用bitmap索引,可能會鎖表,引起業務hang住


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM