sql优化实例oracle,Oracle性能优化-SQL优化(案例三)

Oracle

性能优化

-SQL

优化

(

案例三

)

问题:

客户反馈取消记账耗时太长,10

分钟也结束不了。

问题分析:

问题重现后,远程查看主要慢在一条查询SQL

11df3edba2dc6c35d7c11fb536d3f002.png

查看执行计划gl_voucher

大表全表扫描,实际上

SQL

中谓词字段上有特别高效的索引,怀疑统计信息不准确。

查看gl_voucher

统计信息记录行数

0

行,显然

oracle

认为扫描一个

0

行的表不需要走索引。

SQL> Select * from user_tables where table_name in (

GL_VOUCHER

,

GL_TMP_TABLE

);

24d8ec5807453cd4fc0bbb1bef9859ad.png

解决方案:

手动重新收集gl_voucher

表统计信息

Analyze table gl_voucher compute statistics;

SQL> Select * from user_tables where table_name in (

GL_VOUCHER

,

GL_TMP_TABLE

);

a40f1821d9fc6b024949bcb38bfa8ae2.png

再次执行速度有很大提升。

注意:

统计信息不准确经常会导致性能问题,如果数据库自带收集统计信息的任务已经停了,可以考虑使用如下存储过程定期收集统计信息,此存储过程并不适用于所有场景,根据实际情况进行调整。

---

创建收集统计信息的存储过程:

---需要显式地赋予用户建表权限

grant

create

any

table

to

chen

;

---创建收集统计信息的存储过程

CREATE

OR

REPLACE

PROCEDURE

ANALYZE_TB

AS

OWNER_NAME

VARCHAR2

(

100

);

V_LOG

INTEGER

;

V_SQL1

VARCHAR2

(

800

);

V_TABLENAME

VARCHAR2

(

50

);

CURSOR

CUR_LOG

IS

SELECT

COUNT

(*)

FROM

USER_TABLES

WHERE

TABLE_NAME

=

'ANALYZE_LOG'

;

--1

BEGIN

--DBMS_OUTPUT.ENABLE (buffer_size=>100000);

--1.1

BEGIN

OPEN

CUR_LOG

;

FETCH

CUR_LOG

INTO

V_LOG

;

IF

V_LOG

=

0

THEN

EXECUTE

IMMEDIATE

'CREATE TABLE ANALYZE_LOG (USER_NAME VARCHAR(20),OP_TIME CHAR(19) DEFAULT to_char(sysdate,''yyyy-mm-dd hh24:mi:ss''),ERROR_TEXT VARCHAR(200),TABLE_NAME VARCHAR(40))'

;

END

IF

;

END

;

SELECT

USER

INTO

OWNER_NAME

FROM

DUAL

;

V_SQL1

:=

'INSERT INTO ANALYZE_LOG (USER_NAME,ERROR_TEXT,TABLE_NAME) VALUES ('''

||

OWNER_NAME

||

''',''ANALYZE BEGIN'',''ALL'')'

;

EXECUTE

IMMEDIATE

V_SQL1

;

sys.dbms_stats.gather_schema_stats

(

ownname

=>

UPPER

(

OWNER_NAME

),

estimate_percent

=>

100

,

method_opt

=>

'FOR ALL INDEXED COLUMNS'

,

cascade

=>

TRUE

);

V_SQL1

:=

'INSERT INTO ANALYZE_LOG (USER_NAME,ERROR_TEXT,TABLE_NAME) VALUES ('''

||

OWNER_NAME

||

''',''ANALYZE END'',''ALL'')'

;

EXECUTE

IMMEDIATE

V_SQL1

;

commit

;

--1.2 delete tmptb statitics and lock statistics

BEGIN

for

x

in

(

select

a.table_name

,

a.last_analyzed

,

b.stattype_locked

from

user_tables a

,

user_tab_statistics b

where

a.temporary

=

'Y'

and

a.table_name

=

b.table_name

and

(

b.STATTYPE_LOCKED

is

null

or

a.last_analyzed

is

not

null

))

LOOP

IF

x.last_analyzed

IS

NOT

NULL

THEN

--delete stats

dbms_stats.delete_table_stats

(

ownname

=>

user

,

tabname

=>

x.table_name

,

force

=>

TRUE

);

END

IF

;

IF

x.stattype_locked

IS

NULL

THEN

--lock stats

dbms_stats.lock_table_stats

(

ownname

=>

user

,

tabname

=>

x.table_name

);

END

IF

;

END

LOOP

;

end

;

EXCEPTION

WHEN

OTHERS

THEN

IF

CUR_LOG

%

ISOPEN

THEN

CLOSE

CUR_LOG

;

END

IF

;

commit

;

end

;

---

创建

job,

当天的凌晨2点开始更新统计信息,以后每2天的凌晨2点更新统计信息。

根据实际情况调整时间。

SQL

>

VARIABLE

JOBNO

NUMBER

;

SQL

>

VARIABLE

INSTNO

NUMBER

;

SQL

>

SQL

>

BEGIN

2

SELECT

INSTANCE_NUMBER

INTO

:

INSTNO

FROM

V$INSTANCE

;

3

DBMS_JOB.SUBMIT

(:

JOBNO

,

4

'ANALYZE_TB; '

,

5

TRUNC

(

SYSDATE

)

+

1

+

2

/

24

,

6

'TRUNC(SYSDATE)+2+2/24'

,

7

TRUE

,

8

:

INSTNO

);

9

COMMIT

;

10

END

;

11

/

PL

/

SQL

procedure

successfully completed

欢迎关注我的微信公众号"IT小Chen",共同学习,共同成长!!!

c108d7862b822a619a50eaed2ceeb401.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值