数据库性能优化分析案例---解决SQL语句过度消耗CPU问题

解决|数据|数据库|问题|性能|优化|语句

问题描述:
10月25日上午滨州网通的工程师报告OSS应用系统运行缓慢,具体操作是通过OSS系统查询话单,很长时间才能返回结果,严重影响了客户的正常使用。

问题处理:
1.登陆数据库主机,用sar命令看到idle的值持续为0,CPU的资源已经耗尽:

bz_db1# sar 2 4

SunOS kest 5.8 Generic_108528-19 sun4u    10/26/04

10:56:46    %usr    %sys    %wio   %idle
10:56:48       1       4      95       0
10:56:50       1       5      94       0
10:56:52       0       6      93       0
10:56:54       1       6      93       0

Average        1       5      94      0

2.使用TOP命令看到有两个明显占用CPU利用率过高的进程,以下是top命令的结果:

bz_db1# top

last pid:  1664;load averages:  3.26,  3.24,  3.69                       
159 processes: 152 sleeping, 2 running, 2 zombie, 1 stopped, 2 on cpu
CPU states:  1.5% idle, 72.5% user, 17.9% kernel,  8.0% iowait,  0.0% swap
Memory: 2.0G real, 233M free, 2.0G swap in use, 3.4G swap free

   PID USERNAME THR PR NCE  SIZE   RES STATE   TIME FLTS    CPU COMMAND
 27420 oracle     1 10   0  1.3G  1.2G cpu01  22.9H    2 31.94% oracle
 27418 oracle     1 10   0  1.3G  1.2G run    23.0H    6 26.86% oracle
  5943 oracle     1 59   0  1.3G  1.2G sleep  25:26   37  4.92% oracle
  6295 oracle     1 55   0  1.3G  1.2G run    25:14   74  4.90% oracle
  7778 oracle     1 43   0  1.3G  1.2G sleep  11:43  110  4.86% oracle
 13270 oracle     1 59   0  1.3G  1.2G sleep 210.6H    0  0.96% oracle
 13056 oracle     1 48   0  1.3G  1.2G sleep 303:30    0  0.37% oracle
 10653 root       1 58   0 2560K 1624K cpu00   0:00    0  0.32% top
 18827 oracle     1 58   0  1.3G  1.2G sleep  18.4H    0  0.31% oracle
 12748 oracle   258 58   0  1.3G  1.2G sleep 555:14    0  0.21% oracle
 10634 oracle     1 59   0  1.3G  1.2G sleep   0:01    0  0.21% oracle
 28458 oracle     1 58   0  1.3G  1.2G sleep 535:02    0  0.18% oracle
 13075 oracle     1 59   0  1.3G  1.2G sleep 326:33    0  0.15% oracle
 13173 oracle     1 58   0  1.3G  1.2G sleep 593:07    0  0.13% oracle
  4927 oracle     1 59   0  1.3G  1.2G sleep  33.4H    0  0.11% oracle

可以看到这两个进程号分别是27420和27418.

3.捕获占用CPU利用率过高的SQL语句:

以下用到了我总结的SQL语句:

SQL>set line 240
SQL>set verify off
SQL>column sid format 999
SQL>column pid format 999
SQL>column S_# format 999
SQL>column username format A9 heading "ORA User"
SQL>column program  format a29
SQL>column SQL format a60
SQL>COLUMN OSname format a9 Heading "OS User"
SQL>SELECT P.pid pid,S.sid sid,P.spid spid,S.username username,
S.osuser osname,P.serial# S_#,P.terminal,P.program  program,
P.background,S.status,RTRIM(SUBSTR(a.sql_text, 1, 80))  SQL
FROM v$process P, v$session S,v$sqlarea A WHERE P.addr = s.paddr
AND S.sql_address = a.address (+)  AND P.spid LIKE '%&1%';

Enter value for 1: 27420(注意这里应输入占用CPU最高的进程对应的PID)

得到以下SQL语句:

Select nvl(sum(LOCALCHARGE),0),nvl(sum(usage),0) from LOCALUSAGE where to_char(ENDTIME,'YYYYMMDD')=20041016
and LOCALCHARGE>0 and caller like '0543886%';

27418进程对应的SQL语句如下:
select nvl(sum(LOCALCHARGE),0) from LOCALUSAGE where to_char(ENDTIME,'YYYYMMDD')=20041016 and caller like '0543888%';

4.使用相关用户连接到数据库,检查其执行计划:
SQL>connect wacos/oss
Connected.

SQL>@?/rdbms/admin/utlxplan.sql
Table created.

SQL>set autotrace on

SQL>set timing on

SQL>Select nvl(sum(LOCALCHARGE),0),nvl(sum(usage),0) from LOCALUSAGE where to_char(ENDTIME,'YYYYMMDD')=20041016
 and LOCALCHARGE>0 and caller like '0543886%';

NVL(SUM(LOCALCHARGE),0) NVL(SUM(USAGE),0)
----------------------- -----------------
                      0                 0

Elapsed: 00:02:56.37

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=13435 Card=1 Bytes=5
          3)

   1    0   SORT (AGGREGATE)
   2    1     PARTITION RANGE (ALL)
   3    2       TABLE ACCESS (FULL) OF 'LOCALUSAGE' (Cost=13435 Card=1
          81 Bytes=9593)

Statistics
----------------------------------------------------------
        258  recursive calls
          0  db block gets
      88739  consistent gets
      15705  physical reads
          0  redo size
        580  bytes sent via SQL*Net to client
        651  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          8  sorts (memory)
          0  sorts (disk)
          1  rows processed

发现对localusage表做了全表扫描,什么记录也没有返回居然用了2分多钟。

SQL> select nvl(sum(LOCALCHARGE),0) from LOCALUSAGE where to_char(ENDTIME,'YYYYMMDD')=20040816 and caller like '0543888%';

NVL(SUM(LOCALCHARGE),0)
-----------------------
                   27.6

Elapsed: 00:03:56.46

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=13435 Card=1 Bytes=4
          0)

   1    0   SORT (AGGREGATE)
   2    1     PARTITION RANGE (ALL)
   3    2       TABLE ACCESS (FULL) OF 'LOCALUSAGE' (Cost=13435 Card=3
          615 Bytes=144600)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      88588  consistent gets
      15615  physical reads
          0  redo size
        507  bytes sent via SQL*Net to client
        651  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

这个SQL语句有结果返回,发现也是对localusage表做了全表扫描,但速度也很慢,用了3分多钟。

SQL> select count(*) from localusage;

  COUNT(*)
----------
   5793776

该表有579万多条记录,数据量很大,全表扫描已经不再适合。

5.检查该表的类型:

SQL> SELECT INDEX_NAME, TABLE_NAME, STATUS, PARTITIONED FROM USER_INDEXES WHERE TABLE_NAME='LOCALUSAGE';

INDEX_NAME                     TABLE_NAME                     STATUS   PAR
------------------------------ ------------------------------ -------- ---
I_LOCALUSAGE_SID               LOCALUSAGE                     N/A      YES
UI_LOCALUSAGE_ST_SEQ           LOCALUSAGE                     N/A      YES

SQL> SELECT index_name,table_name,locality FROM user_part_indexes where table_name='LOCALUSAGE';

INDEX_NAME                     TABLE_NAME                     LOCALI
------------------------------ ------------------------------ ------
I_LOCALUSAGE_SID               LOCALUSAGE                     LOCAL
UI_LOCALUSAGE_ST_SEQ           LOCALUSAGE                     LOCAL

发现该表是分区表,并在SERVICEID,STARTIME和CDRSEQUENCE列上建立了分区索引,索引类型是local索引。

6.查看分区索引的索引键值:

SQL> select INDEX_NAME,COLUMN_NAME,INDEX_OWNER from dba_ind_columns where TABLE_NAME='LOCALUSAGE';

INDEX_NAME           COLUMN_NAME          INDEX_OWNER
-------------------- -------------------- ------------------------------
I_LOCALUSAGE_SID     SERVICEID            WACOS
UI_LOCALUSAGE_ST_SEQ STARTTIME            WACOS
UI_LOCALUSAGE_ST_SEQ CDRSEQUENCE          WACOS

发现在endtime和caller列上都没有建立索引,这也是导致SQL语句做全表扫描的最终原因。

7.决定创建新的分区索引以消除全表扫描:

(1).首先查看localusage表分区情况:

SQL> select PARTITION_NAME,tablespace_name from user_tab_partitions where table_name='LOCALUSAGE';

PARTITION_NAME                 TABLESPACE_NAME
------------------------------ ------------------------------
LOCALUSAGE_200312              WACOS
LOCALUSAGE_200401              WACOS
LOCALUSAGE_200402              WACOS
LOCALUSAGE_200404              WACOS
LOCALUSAGE_200405              WACOS
LOCALUSAGE_200406              WACOS
LOCALUSAGE_200407              WACOS
LOCALUSAGE_200409              WACOS
LOCALUSAGE_200410              WACOS
LOCALUSAGE_200411              WACOS
LOCALUSAGE_200403              WACOS
LOCALUSAGE_200408              WACOS
LOCALUSAGE_200412              WACOS

13 rows selected.

(2).在caller列上创建local分区索引:
SQL>set timing on
SQL>create index I_LOCALUSAGE_CALLER on localusage(caller)
LOCAL
(      
        PARTITION LOCALUSAGE_200312,
 PARTITION LOCALUSAGE_200401,
 PARTITION LOCALUSAGE_200402,
 PARTITION LOCALUSAGE_200404,
 PARTITION LOCALUSAGE_200405,
 PARTITION LOCALUSAGE_200406,
 PARTITION LOCALUSAGE_200407,
 PARTITION LOCALUSAGE_200409,
 PARTITION LOCALUSAGE_200410,
 PARTITION LOCALUSAGE_200411,
 PARTITION LOCALUSAGE_200403,
 PARTITION LOCALUSAGE_200408,
 PARTITION LOCALUSAGE_200412
)
TABLESPACE wacos
STORAGE(
 INITIAL 6553600
 NEXT 6553600
 MAXEXTENTS unlimited
 PCTINCREASE 0)
 PCTFREE 5
 NOLOGGING;

Index created.

Elapsed: 00:06:27.90  (由于数据量比较大,耗时6分钟)

8.再次查看执行计划:
SQL>Select nvl(sum(LOCALCHARGE),0),nvl(sum(usage),0) from LOCALUSAGE where to_char(ENDTIME,'YYYYMMDD')=20041016
and LOCALCHARGE>0  and caller like '0543886%';

NVL(SUM(LOCALCHARGE),0) NVL(SUM(USAGE),0)
----------------------- -----------------
                      0                 0

Elapsed: 00:00:03.00

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=22 Card=1 Bytes=53)
   1    0   SORT (AGGREGATE)
   2    1     PARTITION RANGE (ALL)
   3    2       TABLE ACCESS (BY LOCAL INDEX ROWID) OF 'LOCALUSAGE' (Cost=22 Card=181 Bytes=9593)
   4    3         INDEX (RANGE SCAN) OF 'I_LOCALUSAGE_CALLER' (NON-UNIQUE) (Cost=14 Card=65063)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      16813  consistent gets
        569  physical reads
          0  redo size
        580  bytes sent via SQL*Net to client
        651  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

这次走了索引后速度明显快多了,用了3秒钟就返回了结果。

SQL>select nvl(sum(LOCALCHARGE),0) from LOCALUSAGE where to_char(ENDTIME,'YYYYMMDD')=20040816 and caller like '0543888%';

NVL(SUM(LOCALCHARGE),0)
-----------------------
                   27.6

Elapsed: 00:00:24.73

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=22 Card=1 Bytes=40)
   1    0   SORT (AGGREGATE)
   2    1     PARTITION RANGE (ALL)
   3    2       TABLE ACCESS (BY LOCAL INDEX ROWID) OF 'LOCALUSAGE' (Cost=22 Card=3615 Bytes=144600)
   4    3         INDEX (RANGE SCAN) OF 'I_LOCALUSAGE_CALLER' (NON-UNIQUE) (Cost=14 Card=65063)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
     129336  consistent gets
       7241  physical reads
          0  redo size
        507  bytes sent via SQL*Net to client
        651  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

这个SQL语句走了索引,用了24秒钟返回结果,性能明显提高了很多。

时间: 2024-12-13 20:26:51

数据库性能优化分析案例---解决SQL语句过度消耗CPU问题的相关文章

阿里云数据库CloudDBA智慧解决数据库性能优化和问题诊断难题

背景 我要申请CloudDBA免费体验     阿里云数据库为何推出CloudDBA?问题诊断(trouble shooting) 和 性能优化(performance tunning) 一直都是数据库领域的专业问题,需要资深DBA的专业技能才能胜任解决,但这样的人才是稀缺的,无法及时满足大部分的企业紧急需求.如果有一款产品能够在大多数情况下,客户借助它非常迅速的找出数据库性能隐患点.排查出问题症结所在,这将无疑协助客户解决燃眉之急,可以大大降低风险和提高效率.        先来分析下为什么数

《Oracle数据库性能优化方法论和最佳实践》——第2章 Oracle性能优化方法论的发展 2.1 基于局部命中率分析的优化方法论

第2章 Oracle性能优化方法论的发展 Oracle数据库在开发和使用过程中对数据库的性能优化极为重视,几乎在每个版本的更新中都会对可优化的数据库做出改善.不仅如此,Oracle数据库还会使用优化方法来指导性能优化,会不断推出新的性能优化方法论,并依据优化方法论持续完善其可观察的性能优化体系.从Oracle 6到现在的Oracle 12c,经历了Oracle 7.Oracle 8.Oracle 8i.Oracle 9i & R2.Oracle 10gR1 & R2.Oracle 11gR

突破瓶颈 数据库性能优化“路线图”

数据交互复杂度与频度的提升,导致了数据库在运维.迁移和规模扩展进程中的性能问题.作为一项确保企业IT基础部件健康运营的关键技术,数据库性能优化的实现路径和IT系统管理架构越来越密不可分. 南方某省级电信运营商的计费业务营账系统在上线运行后不久即出现性能问题.主要问题表现在最终用户的交互响应达不到预期,特别是在业务繁忙时段无法做出及时响应.从主机系统的角度观察,问题主要集中在系统的I/O(输入/输出)等待较大.而该营账系统由业务应用程序.甲骨文数据库.IBM AIX主机.IBM企业级存储服务器等部

DBA不失业:云时代的数据库性能优化全攻略

性能问题是数据库中最重要也是最迫切要解决的问题之一,随着业务的发展和数据的不断加增,用户对于系统的响应速度的要求越来越高.而归根结底就是要提高数据库系统的性能.对于大部分的DBA来说,性能优化并不是一件容易的事情,造成性能问题的原因多种多样,在现实中,优化过程也会受到重重阻碍,随着云时代的到来以及自动化智能化运维的发展,那么云时代的DBA该如何优化数据库的性能呢? 在今年的数据技术嘉年华上,我们邀请了来自国内外各大企业的性能优化专家,从不同的角度分析云时代数据库性能优化的技术与技巧. 重点嘉宾与

历年双11实战经历者:我们是如何做数据库性能优化及运维-CloudDBA和天象

8月24日阿里云数据库技术峰会上,阿里云高级DBA专家玄惭带来面对超大规模的数据库集群,尤其是在每年像双11这样重大促销活动中,阿里云是如何进行运维和优化的.本文主要介绍了天象和CloudDBA两个产品,包括他们的起源.基于系统画像仓库的应用.产品化等,最后对RDS产品的可诊断性建设和可运维性建设作了补充.   随着云数据库时代的到来,它的运维体系不仅仅包括保持数据库集群的稳定,同时我们还要关注用户体验.在业务上,体量大,用户各类,例如有公有云小客户,也有企业大客户,每类客户的需求都各式不一,众

《Oracle数据库性能优化方法论和最佳实践》——2.6 流程、资源和组件优化方法论

2.6 流程.资源和组件优化方法论 流程.资源和组件优化方法论是本书几位作者综合多年性能优化方法论实践提出的最新的Oracle业务系统性能优化方法论.流程.资源和组件优化方法论以流程响应分析为核心,辅助以流程处理的组件和涉及的资源分析,发现导致性能问题的根本原因,并采取适当的手段进行性能改善.本书从流程.资源和组件优化方法论出发,全面构建性能优化的可测量体系,并通过大量的性能优化实践案例来验证方法论的有效性.2.6.1 吞吐量和响应时间关系曲线 吞吐量和响应时间关系曲线是流程.资源和组件优化方法

Oracle 数据库性能优化3日实战(企业培训)

课程名称一: Oracle性能优化及调整 课程时长 1天 课程深度: 高级 上机实验: 10%-30% 授课对象: Oracle开发人员.Oracle数据库管理人员,应用程序开发人员 课程描述: 本课程讲述Oracle数据库物理层规划,系统性能的监控,数据库性能参数调整,统计信息的收集,使用自动化调试工具优化数据库,I/O子系统的配置与设计以及性能优化方法论等. 预备知识: 熟悉操作系统相关(含Linux)基础知识,具备中级以上数据库相关的基础知识,对Oracle数据库体系结构有深入的理解, 熟

阿里云推出CloudDBA,解数据库性能优化难题

本文讲的是阿里云推出CloudDBA,解数据库性能优化难题[IT168 资讯]问题诊断(trouble shooting) 和 性能优化(performance tunning) 一直都是数据库领域的专业问题,需要资深DBA的专业技能才能胜任解决,但这样的人才是稀缺的,无法及时满足大部分的企业紧急需求.如果有一款产品能够在大多数情况下,用户借助它能非常迅速的找出数据库性能隐患点.排查出问题症结所在,这将无疑协助用户解决燃眉之急,可以大大降低业务风险和提高效率. 在上周发布性能超越Aurora的自

《Oracle数据库性能优化方法论和最佳实践》——1.3 吞吐量和响应时间

1.3 吞吐量和响应时间 吞吐量和响应时间是衡量Oracle业务系统的基本指标,也是业务系统性能的终极指标.如何选择恰当的指标单元来描述吞吐量和响应时间,并且熟练运用吞吐量和响应时间之间的关系是性能优化工作者最为重要的学习和实践.吞吐量和响应时间的关系曲线如此重要,以至于本书几乎所有的章节都是为了帮助大家更好地选择恰当的吞吐量指标,以及更好地理解吞吐量和响应时间的关系曲线.Oracle虽然从Oracle 10gR1就开始提供Time Based Analyze(TBA)性能优化分析方法论,但显然