oracle——SQL复习10

本文深入探讨了Oracle数据库中不同类型的分区表实现方式及其性能对比,包括范围分区、列表分区、Hash分区以及组合分区等,并通过具体示例展示了如何创建这些分区表及验证其效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

--Purge和drop的区别:Oracle 10g提供的flashback drop 新特性为了加快用户错误操作的恢复
--添加purge,是彻底drop 不能在回收站中回复drop掉的对象
 
drop table norm_tab purge;

create table norm_tab (
id number,
deal_date date,
area_code number,
contents varchar2(4000)
) ;

insert into norm_tab 
select   rownum
        ,to_date( to_char(add_months(sysdate,-18),'J') + trunc(dbms_random.value(0,366)),'J') 
        ,trunc(dbms_random.value(400,410)) 
        ,rpad('1',400,'bawoaini') 
from dual 
connect by rownum <= 500000 ;

commit;
select count(1) from  norm_tab t
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD')  ;




/**==============================begin range =====================================*/
/**范围  分区*/
drop table range_part_tab purge ;

create table range_part_tab (
id number,
deal_date date,
area_code number,
contents varchar2(4000)
)
partition by range(deal_date)(
      partition par_list_01 values less than(to_date('20150201','YYYYMMDD')),  
      partition par_list_02 values less than(to_date('20150301','YYYYMMDD')), 
      partition par_list_03 values less than(to_date('20150401','YYYYMMDD')), 
      partition par_list_04 values less than(to_date('20150501','YYYYMMDD')), 
      partition par_list_05 values less than(to_date('20150601','YYYYMMDD')), 
      partition par_list_06 values less than(to_date('20150701','YYYYMMDD')), 
      partition par_list_07 values less than(to_date('20150801','YYYYMMDD')), 
      partition par_list_08 values less than(to_date('20150901','YYYYMMDD')),   
      partition par_list_09 values less than(to_date('20151001','YYYYMMDD')), 
      partition par_list_10 values less than(to_date('20151101','YYYYMMDD')), 
      partition par_list_11 values less than(to_date('20151201','YYYYMMDD')), 
      partition par_list_12 values less than(to_date('20160101','YYYYMMDD')), 
      partition par_list_max values less than(maxvalue)  
);




insert into range_part_tab 
select   rownum
        ,to_date( to_char(add_months(sysdate,-18),'J') + trunc(dbms_random.value(0,366)),'J') 
        ,trunc(dbms_random.value(400,410)) 
        ,rpad('1',400,'bawoaini') 
from dual 
connect by rownum <= 500000 ;

commit;



select count(1) from  range_part_tab t
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD')  ;

/**==============================range end=====================================*/





/**==============================begin list=====================================*/
--列表分区
DROP TABLE list_part_tab purge; 

CREATE TABLE list_part_tab
   ( 
   id number,
   deal_date date,
   area_code number,
   contents varchar2(4000)
   )  
 partition by list(area_code)  
    (  
      partition a400 values('400'),  
      partition a401 values('401'),  
      partition a402 values('402'),  
      partition a403 values('403'),  
      partition a404 values('404'),  
      partition a405 values('405'),  
      partition a406 values('406'),  
      partition a407 values('407'),  
      partition a408 values('408'), 
      partition a409 values('409') 
    )  ;
    


insert into list_part_tab 
select   rownum
        ,to_date( to_char(add_months(sysdate,-18),'J') + trunc(dbms_random.value(0,366)),'J') 
        ,trunc(dbms_random.value(400,410)) 
        ,rpad('1',400,'bawoaini') 
from dual 
connect by rownum <= 500000 ;
commit;
    
--对比普通表 数据块 
select count(1) from  list_part_tab t
where t.area_code between 400 and 401 ; 

select count(1) from  norm_tab t
where t.area_code between 400 and 401 ;


select count(1) from  list_part_tab t
where t.area_code = 400  ;


/**==============================end  list  =====================================*/




/**==============================hash begin =====================================*/
--HASH分区   
DROP TABLE HASH_PART_TAB purge;
 
CREATE TABLE HASH_PART_TAB
   ( 
   ID NUMBER,
   DEAL_DATE DATE,
   AREA_CODE NUMBER,
   CONTENTS VARCHAR2(4000)
   )   
PARTITION BY HASH(DEAL_DATE)  
PARTITIONS 12 ;  


insert into HASH_PART_TAB 
select   rownum
        ,to_date( to_char(add_months(sysdate,-18),'J') + trunc(dbms_random.value(0,366)),'J') 
        ,trunc(dbms_random.value(400,410)) 
        ,rpad('1',400,'bawoaini') 
from dual 
connect by rownum <= 500000 ;

commit;

select count(1) from  hash_part_tab t
where t.area_code = 400   ;


select count(1) from  hash_part_tab t
where t.deal_date between to_date('20150701','YYYYMMDD') and to_date('20150731','YYYYMMDD') ; 


select count(1) from  hash_part_tab t
where t.deal_date = to_date('20150723','YYYYMMDD') ; 

--显示当前用户所有分区表的信息:
select t.table_name , t.owner  from ALL_PART_TABLES t  where t.owner = 'SCOTT';
--显示表分区信息 显示数据库所有分区表的详细分区信息:
select t.table_name ,t.partitioning_type,t.partition_count  from  USER_PART_TABLES  t;
--显示当前用户可访问的所有分区表的详细分区信息:
select t.table_name,t.table_owner,t.partition_name ,t.partition_position from DBA_TAB_PARTITIONS t
where t.table_owner = 'SCOTT' ;
  

--疑问: 不是说hash分区是根据hash算法,将数据均匀分散到各个分区表中,但为什么他们的数据量count(1)是不一样的 
-- 所谓的均匀分布到各个分区表,应该怎么验证????
select  'p21', count(1) from HASH_PART_TAB partition(SYS_P21) union all 
select  'p22', count(1) from HASH_PART_TAB partition(SYS_P22) union all 
select  'p23', count(1) from HASH_PART_TAB partition(SYS_P23) union all 
select  'p24', count(1) from HASH_PART_TAB partition(SYS_P24) union all 
select  'p25', count(1) from HASH_PART_TAB partition(SYS_P25) union all 
select  'p26', count(1) from HASH_PART_TAB partition(SYS_P26) union all 
select  'p27', count(1) from HASH_PART_TAB partition(SYS_P27) union all 
select  'p28', count(1) from HASH_PART_TAB partition(SYS_P28) union all 
select  'p29', count(1) from HASH_PART_TAB partition(SYS_P29) union all 
select  'p30', count(1) from HASH_PART_TAB partition(SYS_P30) union all 
select  'p31', count(1) from HASH_PART_TAB partition(SYS_P31) union all 
select  'p32', count(1) from HASH_PART_TAB partition(SYS_P32)  ; 

/**==============================hash    end=====================================*/





/**==============================begin range_list =====================================*/
--组合分区: 范围 列表分区

drop table range_list_part_tab purge; 

create table range_list_part_tab (
id number,
deal_date date,
area_code number,
contents varchar2(4000)
)
partition by range(deal_date)
 subpartition by list(area_code)  
 subpartition template 
    (  
      subpartition  a400 values('400'),  
      subpartition a401 values('401'),  
      subpartition a402 values('402'),  
      subpartition a403 values('403'),  
      subpartition a404 values('404'),  
      subpartition a405 values('405'),  
      subpartition a406 values('406'),  
      subpartition a407 values('407'),  
      subpartition a408 values('408'), 
      subpartition a409 values('409') 
    )  
(
      partition par_list_01 values less than(to_date('20150201','YYYYMMDD')),  
      partition par_list_02 values less than(to_date('20150301','YYYYMMDD')), 
      partition par_list_03 values less than(to_date('20150401','YYYYMMDD')), 
      partition par_list_04 values less than(to_date('20150501','YYYYMMDD')), 
      partition par_list_05 values less than(to_date('20150601','YYYYMMDD')), 
      partition par_list_06 values less than(to_date('20150701','YYYYMMDD')), 
      partition par_list_07 values less than(to_date('20150801','YYYYMMDD')), 
      partition par_list_08 values less than(to_date('20150901','YYYYMMDD')),   
      partition par_list_09 values less than(to_date('20151001','YYYYMMDD')), 
      partition par_list_10 values less than(to_date('20151101','YYYYMMDD')), 
      partition par_list_11 values less than(to_date('20151201','YYYYMMDD')), 
      partition par_list_12 values less than(to_date('20160101','YYYYMMDD')), 
      partition par_list_max values less than(maxvalue)  
);



insert into range_list_part_tab 
select   rownum
        ,to_date( to_char(add_months(sysdate,-18),'J') + trunc(dbms_random.value(0,366)),'J') 
        ,trunc(dbms_random.value(400,410)) 
        ,rpad('1',400,'bawoaini') 
from dual 
connect by rownum <= 500000 ;
commit;


 
--查询某段时间内 , 某地区的数据 
 
--结论: 以下语句, 范围分区要比  组合分区(范围列表分区)     性能 差不多
--   consistent gets:29566    Cost (%CPU):6507 time: 00:01:19
select count(1) from  norm_tab t
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD')   
and t.area_code between 400 and 401     
-- consistent gets :2518   Cost (%CPU):  508   TIME:00:00:07
select count(1) from  range_part_tab t
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD')   
and t.area_code between 400 and 401  
-- consistent gets: 1190 Cost (%CPU): 557  TIME:00:00:07
select count(1) from  range_list_part_tab t
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD')   
and t.area_code between 400 and 401 ;

 



--   consistent gets: 29566    Cost (%CPU): 6506
select count(1) from  norm_tab t
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD') ;
-- consistent gets :2569     Cost (%CPU): 583
select count(1) from  range_part_tab t
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD')  ;  
-- consistent gets: 4812     Cost (%CPU):  1435          
select count(1) from  range_list_part_tab t
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD')    ;




 

--   consistent gets: 29566    Cost (%CPU): 6507
select count(1) from  norm_tab t
where   t.area_code between 400 and 401     ;
-- consistent gets :29922    Cost (%CPU):  6580
select count(1) from  range_part_tab t
where  t.area_code between 400 and 401  ;
-- consistent gets: 11758    Cost (%CPU):  1416  
select count(1) from  range_list_part_tab t
where  t.area_code between 400 and 401 ;


--结论: 以下语句, 组合分区(范围列表分区)要比  范围分区性能 更快 

-- consistent gets :29489    Cost (%CPU): 6507   time: 00:01:19
select count(1) from  norm_tab t  
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD')     
and t.area_code  = 400     ;
-- consistent gets :2518    Cost (%CPU): 556   time:00:00:07
select count(1) from  range_part_tab t  
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD')     
and t.area_code = 400    ;
-- consistent gets: 297    Cost (%CPU):  69     time:00:00:01
select count(1) from  range_list_part_tab t  
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD')     
and t.area_code = 400; 


/**==============================end  range list  =====================================*/




/*在cmd 中 sqlplus使用以下语句查看sql的执行计划  */
sqlplus scott/tiger
set autotrace on;
set linesize 1000;
set timing on;


--组合分区: 范围 hash分区




/**

select count(1) from norm_tab ;


select count(1) from  list_part_tab t
where t.deal_date between to_date('20150301','YYYYMMDD') and  to_date('20150331','YYYYMMDD')  ;

--
select  trunc(dbms_random.value(400,410)) from dual ;



--1select rownum from dual connect by rownum <=100;--2select to_date( to_char(sysdate,'J') ,'J') from dual ; select trunc(dbms_random.value(0,10)) from dual; select to_date( to_char(add_months(sysdate,-18),'J') + trunc(dbms_random.value(0,366)),'J') from dual ;--3select trunc(dbms_random.value(400,410)) from dual ;--4select rpad('1',400,'bawoaini') from dual; */select to_char(sysdate,'J') from dual ;select to_date( to_char(sysdate,'J') ,'J') from dual ;--1721424select to_char(to_date('00010101','YYYYMMDD'),'J') from dual ;--5373484select to_char(to_date('99991231','YYYYMMDD'),'J') from dual ;select to_date(1721424 ,'J') from dual ;select to_date( to_char(to_date('00010101','YYYYMMDD'),'J') ,'J') from dual ;--0001-1-2select to_date(1721425,'J') from dual ; select to_date(5373483,'J') from dual ;select to_char(add_months(sysdate,-12),'J') from dual ; select to_char(sysdate,'J') - to_char(add_months(sysdate,-12),'J') from dual ;--SYEAR或YEAR SYEAR使公元前的年份前加一负号 -1112表示公元前111 2年select to_date('47120101','YYYYMMDD') from dual; Select to_char(to_date('47120101','YYYYMMDD'),'-year') from dual; Select to_char(to_date('47120101','YYYYMMDD'),'YY') from dual; Select to_char(to_date('47120101','YYYYMMDD'),'YYYY') from dual; Select to_char(to_date('47120101','YYYYMMDD'),'year') from dual; Select to_char(to_date('47120101','YYYYMMDD'),'month') from dual; Select to_char(to_date('47120101','YYYYMMDD'),'dd') from dual; --select to_date('-47130101','YYYYMMDD') from dual; Select to_char(sysdate,'SYEAR') from dual; SELECT months_between(sysdate,to_date('47120101','YYYYMMDD')) FROM DUAL; select length(rpad('1',400,'*')) from dual ;



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值