如何最大限制利用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