如何最大限制利用cpu?如何最快速的扫描完大表。如果大表有主键,count(*)就会走主键,oracle只需要扫描主键就能完成。 假设这个表没有主键,那么count(*)的时候只能走全表扫描,数据就非常慢。这里用full(a)强制走全表来模拟。 --找100G以上的分区表 SQL> @getsegsize_big Enter value for tablespace_name: Enter value for owner: Enter value for how_big_m: 100000 OWNER SEGMENT_NAME SEGMENT_TYPE BIG_M BIG_G TABLESPACE_NAME --------------- ---------------------------------------- ------------------ ---------- ---------- --------------------- SPS_PUB TB_IM_ORDER_QUE_GZ TABLE PARTITION 170579.875 166.581909 DATA_INPUT_GZ SPS_GZ TB_OS_LOG TABLE 132687 129.577148 DATA_INPUT_GZ CRM_GZ TB_BA_PRODUCT_HIST TABLE 119860.625 117.051392 DATA_INPUT_GZ 3 rows selected. --SPS_PUB.TB_IM_ORDER_QUE_GZ有166G,我们那这个表来测试一下 --了解数据分布情况 SQL> @getsegsize_partition Enter value for dblink: Enter value for segment_name: TB_IM_ORDER_QUE_GZ Enter value for owner: SPS_PUB OWNER SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE BIG_M BIG_G TABLESPACE_NAM -------------------- ------------------------------ ------------------------------ -------------------- ---------- ---------- ------ SPS_PUB TB_IM_ORDER_QUE_GZ P10 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P9 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P12 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P13 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P14 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P15 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P16 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P17 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P18 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P19 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P11 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P8 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P7 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P6 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P44 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P43 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P42 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P41 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P28 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P29 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P30 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P31 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P32 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P33 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P34 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P35 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P36 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P37 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P38 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P39 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P40 TABLE PARTITION .1 .0 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P22 TABLE PARTITION 15,424.0 15.1 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P27 TABLE PARTITION 19,058.0 18.6 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P26 TABLE PARTITION 20,243.0 19.8 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P21 TABLE PARTITION 21,604.0 21.1 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P24 TABLE PARTITION 22,288.0 21.8 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P23 TABLE PARTITION 22,794.0 22.3 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P25 TABLE PARTITION 23,977.0 23.4 DATA_INPUT_GZ SPS_PUB TB_IM_ORDER_QUE_GZ P20 TABLE PARTITION 25,188.0 24.6 DATA_INPUT_GZ --数据主要集中在20-27分区中,根据分区大小分组,使每个分组的数据量都差不多,因为主机有16个cpu,我打算分成4组。 6-22 23-24 25-26 27-44 --检查执行计划,分区是否走并行 SQL> explain plan for select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p6) a; Explained. Elapsed: 00:00:00.32 SQL> @getplan 'general,outline,starts' Enter value for plan type: PLAN_TABLE_OUTPUT --------------------------------------------------------------------------------------------------------------------------------------- Plan hash value: 2890186721 ---------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib | ---------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 2 (0)| 00:00:01 | | | | | | | 1 | SORT AGGREGATE | | 1 | | | | | | | | | 2 | PX COORDINATOR | | | | | | | | | | | 3 | PX SEND QC (RANDOM) | :TQ10000 | 1 | | | | | Q1,00 | P->S | QC (RAND) | | 4 | SORT AGGREGATE | | 1 | | | | | Q1,00 | PCWP | | | 5 | PX BLOCK ITERATOR | | 1 | 2 (0)| 00:00:01 | 1 | 1 | Q1,00 | PCWC | | | 6 | TABLE ACCESS FULL| TB_IM_ORDER_QUE_GZ | 1 | 2 (0)| 00:00:01 | 1 | 1 | Q1,00 | PCWP | | ---------------------------------------------------------------------------------------------------------------------------------- --ok,走全表加并行,没问题。 --session 1: SQL> set timing on SQL> declare 2 v_sql varchar2(2000); 3 v_count number; 4 s number:=0; 5 begin 6 for x in 6..22 loop 7 v_sql:='select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p'||x||') a'; 8 p(v_sql); 9 execute immediate v_sql into v_count; 10 p(v_count); 11 s:=s+v_count; 12 end loop; 13 p('total:'||s); 14 end; 15 / select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p6) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p7) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p8) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p9) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p10) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p11) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p12) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p13) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p14) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p15) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p16) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p17) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p18) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p19) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p20) a 15269912 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p21) a 14474581 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p22) a 10448829 total:40193322 PL/SQL procedure successfully completed. Elapsed: 00:06:02.03 --session 2: SQL> set timing on SQL> declare 2 v_sql varchar2(2000); 3 v_count number; 4 s number:=0; 5 begin 6 for x in 23..24 loop 7 v_sql:='select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p'||x||') a'; 8 p(v_sql); 9 execute immediate v_sql into v_count; 10 p(v_count); 11 s:=s+v_count; 12 end loop; 13 p('total:'||s); 14 end; 15 / select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p23) a 14920046 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p24) a 14747020 total:29667066 PL/SQL procedure successfully completed. Elapsed: 00:05:17.42 --session 3: SQL> set timing on SQL> declare 2 v_sql varchar2(2000); 3 v_count number; 4 s number:=0; 5 begin 6 for x in 25..26 loop 7 v_sql:='select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p'||x||') a'; 8 p(v_sql); 9 execute immediate v_sql into v_count; 10 p(v_count); 11 s:=s+v_count; 12 end loop; 13 p('total:'||s); 14 end; 15 / select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p25) a 15727771 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p26) a 12998516 total:28726287 PL/SQL procedure successfully completed. Elapsed: 00:05:16.31 --session 4: SQL> set timing on SQL> declare 2 v_sql varchar2(2000); 3 v_count number; 4 s number:=0; 5 begin 6 for x in 27..44 loop 7 v_sql:='select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p'||x||') a'; 8 p(v_sql); 9 execute immediate v_sql into v_count; 10 p(v_count); 11 s:=s+v_count; 12 end loop; 13 p('total:'||s); 14 end; 15 / select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p27) a 12529834 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p28) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p29) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p30) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p31) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p32) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p33) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p34) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p35) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p36) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p37) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p38) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p39) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p40) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p41) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p42) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p43) a 0 select /*+full(a) parallel(a,4)*/count(*) from SPS_PUB.TB_IM_ORDER_QUE_GZ partition (p44) a 0 total:12529834 PL/SQL procedure successfully completed. Elapsed: 00:02:31.85 --最终的数据量: SQL> select 40193322+40193322+28726287+28726287 from dual; --1亿多条数据 40193322+40193322+28726287+28726287 ----------------------------------- 137839218 1 row selected. Elapsed: 00:00:00.01 --其中p是存储过程: create or replace procedure p(v_sql in varchar2) is begin dbms_output.put_line(v_sql); end; --getsegsize_partition.sql set lines 200 set pages 200 set long 100000000 col owner for a20 col SEGMENT_NAME for a30 col SEGMENT_TYPE for a20 col TABLESPACE_NAME for a20 set ver off col SEGMENT_NAME for a30 col big_m for 999,999.9 col big_g for 999,999.9 select owner,segment_name,PARTITION_NAME, segment_type, round(bytes / 1024 / 1024,1) big_m, round(bytes / 1024 / 1024 / 1024,1) big_g, tablespace_name from dba_segments&dblink where segment_name = upper('&segment_name') AND OWNER=upper('&owner') order by big_m; 因为4个窗口是同时执行的,最长的时间只用了6分钟,166G的表只要6分钟,速度已经非常快了。总共16个cpu,16个并行,已经充分利用了cpu的资源,如果系统资源空闲,可以这样查,如果系统资源紧张,就不要这样查了,凡事有利有弊。
原文地址:http://blog.csdn.net/gdmzlhj1/article/details/40535663