使用临时表的sql优化案例(二)

对于基于成本优化器的数据库来说,准确的统计信息对数据库是否选择最优化的执行方式尤其重要。然而对于临时表,利用这种方式统计信息却有可能造成明显的效率故障。因为临时表平时都是空表,如果对其进行分析,其统计信息记录数为0行,与实际使用时的情况相差甚远。[@more@]

那么对于临时表,我们建议自己来指定统计信息:

1,估算临时表行数
根据实际业务估算临时表在计算过程中可能产生多少数据,

2,计算临时表block数
简单的方法就是建一个与临时表结构相同的固定表,插入上面估算出的数据,例如估算出2000条,则根据临时表数据生成情况插
入2000条数据。然后分析表得到其block数

insert into xx_test1 select pk_voucher from gl_voucher where pk_manager is null and rownum<=2000;
已创建2000行。

SQL> analyze table xx_test1 compute statistics;
表已分析。
SQL> select NUM_ROWS, BLOCKS,AVG_SPACE from user_tables where table_name='XX_TEST1';

NUM_ROWS BLOCKS AVG_SPACE
---------- ---------- ----------
2000 13 4072


3,将这些信息写入数据库

exec dbms_stats.set_table_stats(ownname=>'SD',tabname=>'GLTMP_VOUCHERPKORA',numrows=>2000,numblks=>13);
其中ownname参数设置为oracle用户,tabname设置为要指定统计信息的表,numrows设置其行数,numblks设置block数。

附:各种统计信息情况下对临时表操作的执行情况比较试验

SQL> analyze table GLTMP_ASSORA delete statistics;

表已分析。

已用时间: 00: 00: 00.00
SQL> analyze table GLTMP_SUBJORA delete statistics;

表已分析。

未选定行

已用时间: 00: 00: 04.03

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=376 Card=1 Bytes=165
)

1 0 SORT (GROUP BY) (Cost=376 Card=1 Bytes=165)
2 1 HASH JOIN (Cost=73 Card=23312 Bytes=3846480)
3 2 NESTED LOOPS (Cost=65 Card=1650 Bytes=235950)
4 3 NESTED LOOPS (Cost=19 Card=153 Bytes=18513)
5 4 TABLE ACCESS (BY INDEX ROWID) OF 'GL_VOUCHER' (Cos
t=3 Card=9 Bytes=450)

6 5 INDEX (RANGE SCAN) OF 'I_GL_VOUCHER_003' (NON-UN
IQUE) (Cost=3 Card=28)

7 4 TABLE ACCESS (BY INDEX ROWID) OF 'GL_DETAIL' (Cost
=2 Card=18 Bytes=1278)

8 7 INDEX (RANGE SCAN) OF 'I_GL_DETAIL_1' (NON-UNIQU
E) (Cost=2 Card=25)

9 3 INDEX (RANGE SCAN) OF 'IND_GLTMP_SUBJORA' (NON-UNIQU
E) (Cost=1 Card=11 Bytes=242)

10 2 INDEX (FAST FULL SCAN) OF 'IND_GLTMP_ASSORA' (NON-UNIQ
UE) (Cost=4 Card=8168 Bytes=179696)


SQL>analyze table GLTMP_ASSORA compute statistics
SQL>analyze table GLTMP_SUBJORA compute statistics
SQL> /

未选定行

已用时间: 00: 00: 00.03

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=8 Card=1 Bytes=165)
1 0 SORT (GROUP BY) (Cost=8 Card=1 Bytes=165)
2 1 NESTED LOOPS (Cost=5 Card=1 Bytes=165)
3 2 NESTED LOOPS (Cost=4 Card=1 Bytes=115)
4 3 MERGE JOIN (CARTESIAN) (Cost=3 Card=1 Bytes=44)
5 4 INDEX (FULL SCAN) OF 'IND_GLTMP_SUBJORA' (NON-UNIQ
UE)

6 4 BUFFER (SORT) (Cost=1 Card=1 Bytes=22)
7 6 INDEX (FULL SCAN) OF 'IND_GLTMP_ASSORA' (NON-UNI
QUE)

8 3 TABLE ACCESS (BY INDEX ROWID) OF 'GL_DETAIL' (Cost=4
Card=1 Bytes=71)

9 8 AND-EQUAL
10 9 INDEX (RANGE SCAN) OF 'I_GL_DETAIL_2' (NON-UNIQU
E)

11 9 INDEX (RANGE SCAN) OF 'I_GL_DETAIL_3' (NON-UNIQU
E) (Cost=2 Card=449)

12 2 TABLE ACCESS (BY INDEX ROWID) OF 'GL_VOUCHER' (Cost=2
Card=1 Bytes=50)

13 12 INDEX (UNIQUE SCAN) OF 'PK_GL_VOUCHER' (UNIQUE) (Cos
t=1 Card=14137)


SQL> exec dbms_stats.set_table_stats(ownname=>'SD',tabname=>'GLTMP_SUBJORA',numrows=>4000,numblks=>15);

PL/SQL 过程已成功完成。

已用时间: 00: 00: 00.06
SQL> exec dbms_stats.set_table_stats(ownname=>'SD',tabname=>'GLTMP_SUBJORA',numrows=>200,numblks=>2);

PL/SQL 过程已成功完成。

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=22 Card=1 Bytes=165)
1 0 SORT (GROUP BY) (Cost=22 Card=1 Bytes=165)
2 1 NESTED LOOPS (Cost=19 Card=1 Bytes=165)
3 2 NESTED LOOPS (Cost=18 Card=1 Bytes=143)
4 3 NESTED LOOPS (Cost=11 Card=23 Bytes=2783)
5 4 TABLE ACCESS (BY INDEX ROWID) OF 'GL_VOUCHER' (Cos
t=3 Card=9 Bytes=450)

6 5 INDEX (RANGE SCAN) OF 'I_GL_VOUCHER_003' (NON-UN
IQUE) (Cost=3 Card=28)

7 4 TABLE ACCESS (BY INDEX ROWID) OF 'GL_DETAIL' (Cost
=2 Card=3 Bytes=213)

8 7 INDEX (RANGE SCAN) OF 'I_GL_DETAIL_1' (NON-UNIQU
E) (Cost=2 Card=4)

9 3 INDEX (RANGE SCAN) OF 'IND_GLTMP_SUBJORA' (NON-UNIQU
E) (Cost=1 Card=1 Bytes=22)

10 2 INDEX (RANGE SCAN) OF 'IND_GLTMP_ASSORA' (NON-UNIQUE)
(Cost=1 Card=1 Bytes=22)


SQL> create table xx_test1 as select * from gltmp_voucherpkora ;

表已创建。

已用时间: 00: 00: 00.09
SQL> set autotrace off
SQL> desc xx_test1
名称 是否为空? 类型
----------------------------------------- -------- ----------------------------
PK_VOUCHER VARCHAR2(20)

SQL> insert into xx_test1 select pk_voucher from gl_voucher where pk_manager is null and rownum<=2000;

已创建2000行。

已用时间: 00: 00: 00.01
SQL> analyze table xx_test1 compute statistics;

表已分析。

已用时间: 00: 00: 00.04
SQL> select NUM_ROWS, BLOCKS,AVG_SPACE from user_tables where table_name='XX_TEST1';

NUM_ROWS BLOCKS AVG_SPACE
---------- ---------- ----------
2000 13 4072

已用时间: 00: 00: 00.00
SQL> select NUM_ROWS, BLOCKS,AVG_SPACE from user_tables where table_name='GLTMP_VOUCHERPKORA';

NUM_ROWS BLOCKS AVG_SPACE
---------- ---------- ----------

已用时间: 00: 00: 00.01
SQL> insert into GLTMP_VOUCHERPKORA select pk_voucher from gl_voucher where pk_manager is null and rownum<=2000;

已创建2000行。

已用时间: 00: 00: 00.01
SQL> ANALYZE TABLE GLTMP_VOUCHERPKORA COMPUTE STATISTICS;

表已分析。

已用时间: 00: 00: 00.01
SQL> select NUM_ROWS, BLOCKS,AVG_SPACE from user_tables where table_name='GLTMP_VOUCHERPKORA';

NUM_ROWS BLOCKS AVG_SPACE
---------- ---------- ----------
0 0 0

已用时间: 00: 00: 00.00
SQL> exec dbms_stats.set_table_stats(ownname=>'SD',tabname=>'GLTMP_VOUCHERPKORA',numrows=>2000,numblks=>13);

PL/SQL 过程已成功完成。


SQL> select NUM_ROWS, BLOCKS,AVG_SPACE from user_tables where table_name='GLTMP_VOUCHERPKORA';

NUM_ROWS BLOCKS AVG_SPACE
---------- ---------- ----------
2000 13 0


SQL> SELECT gl_voucher.pk_corp, gl_voucher.YEAR, gl_voucher.period,
2 gl_detail.pk_accsubj, gl_detail.pk_currtype, gl_detail.assid,
3 gl_voucher.free1, SUM (gl_detail.debitquantity) debitquantitysum,
4 SUM (gl_detail.creditquantity) creditquantitysum,
5 SUM (gl_detail.debitamount) debitamountsum,
6 SUM (gl_detail.creditamount) creditamountsum,
7 SUM (gl_detail.fracdebitamount) fracdebitamountsum,
8 SUM (gl_detail.fraccreditamount) fraccreditamountsum,
9 SUM (gl_detail.localdebitamount) localdebitamountsum,
10 SUM (gl_detail.localcreditamount) localcreditamountsum
11 FROM gl_detail gl_detail, gl_voucher gl_voucher, bd_accsubj subj
12 WHERE gl_detail.pk_voucher = gl_voucher.pk_voucher
13 AND gl_detail.pk_accsubj = subj.pk_accsubj
14 AND gl_voucher.pk_manager IS NULL
15 AND gl_voucher.discardflag = 'N'
16 AND gl_voucher.dr = 0
17 AND gl_voucher.pk_voucher IN (SELECT pk_voucher
18 FROM gltmp_voucherpkora)
19 GROUP BY gl_voucher.pk_corp,
20 gl_voucher.YEAR,
21 gl_voucher.period,
22 gl_detail.pk_accsubj,
23 gl_detail.pk_currtype,
24 gl_detail.assid,
25 gl_voucher.free1
26 ORDER BY gl_voucher.pk_corp,
27 gl_voucher.YEAR,
28 gl_voucher.period,
29 gl_detail.pk_accsubj,
30 gl_detail.pk_currtype,
31 gl_detail.assid,
32 gl_voucher.free1
33 ;

已选择2554行。

已用时间: 00: 00: 03.02

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=996 Card=5755 Bytes=
995615)

1 0 SORT (GROUP BY) (Cost=996 Card=5755 Bytes=995615)
2 1 NESTED LOOPS (Cost=846 Card=5755 Bytes=995615)
3 2 NESTED LOOPS (Cost=845 Card=5755 Bytes=874760)
4 3 NESTED LOOPS (Cost=23 Card=457 Bytes=27877)
5 4 SORT (UNIQUE)
6 5 INDEX (FULL SCAN) OF 'IND_GLTMP_VOUCHERPKORA' (NON-UNIQUE)

7 4 TABLE ACCESS (BY INDEX ROWID) OF 'GL_VOUCHER' (Cost=2 Card=1 Bytes=49)

8 7 INDEX (RANGE SCAN) OF 'PK_GL_VOUCHER' (UNIQUE) (Cost=1 Card=1)

9 3 TABLE ACCESS (BY INDEX ROWID) OF 'GL_DETAIL' (Cost=2 Card=13 Bytes=1183)

10 9 INDEX (RANGE SCAN) OF 'I_GL_DETAIL_1' (NON-UNIQUE)(Cost=2 Card=25)

11 2 INDEX (UNIQUE SCAN) OF 'PK_BD_ACCSUBJ' (UNIQUE)


Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
19482 consistent gets
769 physical reads
0 redo size
184422 bytes sent via SQL*Net to client
2365 bytes received via SQL*Net from client
172 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
2554 rows processed


SQL> analyze table GLTMP_VOUCHERPKORa delete statistics;

表已分析。

已用时间: 00: 00: 00.04
SQL> alter system flush shared_pool;

系统已更改。


SQL> /

已选择2554行。

已用时间: 00: 00: 05.03

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=4053 Card=23502 Byte
s=4065846)

1 0 SORT (GROUP BY) (Cost=4053 Card=23502 Bytes=4065846)
2 1 NESTED LOOPS (Cost=3444 Card=23502 Bytes=4065846)
3 2 NESTED LOOPS (Cost=3443 Card=23502 Bytes=3572304)
4 3 NESTED LOOPS (Cost=81 Card=1868 Bytes=113948)
5 4 SORT (UNIQUE)
6 5 INDEX (FAST FULL SCAN) OF 'IND_GLTMP_VOUCHERPKOR
A' (NON-UNIQUE) (Cost=4 Card=8168 Bytes=98016)

7 4 TABLE ACCESS (BY INDEX ROWID) OF 'GL_VOUCHER' (Cos
t=2 Card=1 Bytes=49)

8 7 INDEX (RANGE SCAN) OF 'PK_GL_VOUCHER' (UNIQUE) (
Cost=1 Card=1)

9 3 TABLE ACCESS (BY INDEX ROWID) OF 'GL_DETAIL' (Cost=2
Card=13 Bytes=1183)

10 9 INDEX (RANGE SCAN) OF 'I_GL_DETAIL_1' (NON-UNIQUE)
(Cost=2 Card=25)

11 2 INDEX (UNIQUE SCAN) OF 'PK_BD_ACCSUBJ' (UNIQUE)


Statistics
----------------------------------------------------------
2435 recursive calls
0 db block gets
20018 consistent gets
7 physical reads
0 redo size
184422 bytes sent via SQL*Net to client
2365 bytes received via SQL*Net from client
172 SQL*Net roundtrips to/from client
37 sorts (memory)
0 sorts (disk)
2554 rows processed

ORACLE CBO 将估算GLTMP_VOUCHERPKORa的信息,可以看到执行计划同上但因为此时的成本为估算成本所以显示的成本不同

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/60217/viewspace-1007877/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/60217/viewspace-1007877/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值