zoukankan      html  css  js  c++  java
  • 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住

  • 相关阅读:
    JS实现checkbox全选功能
    JS回车检索
    MockServer 之postman
    Locust性能测试
    Bitter.Core系列二:Bitter ORM NETCORE ORM 全网最粗暴简单易用高性能的 NETCore ORM 之数据库连接
    MSSQL 经典语句查看表字典结构语句
    使用 Path.Combine 构建跨平台文件路径拼接
    迁移备份WSL2下的子系统/迁移Windows 10 Docker Data目录/踩坑记录
    MSSQL 20212 高可用集群方案2012的AlwaysOn高性能组件
    MSSQL 经典SQL 语句WITH递归
  • 原文地址:https://www.cnblogs.com/hmwh/p/12097483.html
Copyright © 2011-2022 走看看