ORACLE执行的SQL性能分析[超实战版]

一、整体情况分析

  1. 缓冲区命中率:缓冲区命中率表示在不需要进行磁盘访问的情况下在内存结构中找到常用数据块的频率,
    大于98%为最佳
select (1-(sum(decode(name, 'physical reads',value,0))/(sum(decode(name, 'db block gets',value,0)) 
         +sum(decode(name,'consistent gets',value,0))))) * 100 AS "缓冲区命中率"
         from v$sysstat;
  1. 数据字典缓存命中率:数据字典缓存命中率显示了对数据字典和其他对象的内存读操作所占的百分比,
    大于98%为最佳
select (1-(sum(getmisses)/sum(gets))) * 100 AS "数据字典缓存命中率" from v$rowcache;
  1. 库缓存命中率:库缓存命中率显示了对实际语句和PL/SQL对象的内存读操作所占的百分比。

注意,很高的命中率并不总是一件好事,大于98%为最佳

select Sum(Pins)/(Sum(Pins) + Sum(Reloads)) * 100 AS "库缓存命中率" from V$LibraryCache;
  1. PGA内存排序命中率:PGA内存排序率的值应该大于98%。
select 
	a.value "磁盘排序数", 
  b.value "内存排序数",
  round((100*b.value)/decode((a.value+b.value),0,1,(a.value+b.value)),2) AS "PGA内存排序命中率" 
from v$sysstat a, v$sysstat b 
where   a.name = 'sorts (disk)'and b.name = 'sorts (memory)';
  1. 全库最浪费内存的前10个语句占所有语句的比例,在没有调整的情况下,大多数系统中10个最常使用的
    SQL语句的访问量占了整个系统中内存读操作的50%以上。本节测量了最影响性能的代码对整个系统所造成
    危害的严重性,以百分比表示。小于5%为最佳
select sum(pct_bufgets) AS "内存浪费率" from (
	select rank() over ( order by s.buffer_gets desc ) as rank_bufgets,
  to_char(100 * ratio_to_report(s.buffer_gets) over (),'990.99') pct_bufgets 
  from v$sqlarea s
  ) where rank_bufgets < 11;
  1. 全库内存浪费率SQL排序
select 
	s.sql_id,s.SQL_FULLTEXT,s.MODULE,
	rank() over ( order by s.buffer_gets desc ) as rank_bufgets,
  to_char(100 * ratio_to_report(buffer_gets) over (),'990.99') pct_bufgets 
from v$sqlarea s;
  1. 关注的用户最浪费内存的前10个语句占所有语句的比例,在没有调整的情况下,

    大多数系统中10个最常使用的SQL语句的访问量占了整个系统中内存读操作的50%以上。
    本节测量了最影响性能的代码对整个系统所造成危害的严重性,以百分比表示。小于5%为最佳

SELECT sum(pct_bufgets) AS "内存浪费率" from (
	select 
  	rank() over ( order by s.buffer_gets desc ) as rank_bufgets,
    to_char(100 * ratio_to_report(s.buffer_gets) over (),'990.99') pct_bufgets 
  from v$sqlarea s
  LEFT JOIN dba_hist_sqlstat h ON s.SQL_ID=h.sql_id AND h.parsing_schema_name IN('EREFORM','INTERNET_HOSPITAL')
  WHERE s.MODULE='w3wp.exe'
) where rank_bufgets < 11;
  1. 关注的用户内存浪费率SQL排序
select 
	s.sql_id,s.SQL_FULLTEXT,h.parsing_schema_name,s.MODULE,
	rank() over ( order by s.buffer_gets desc ) as rank_bufgets,
  to_char(100 * ratio_to_report(buffer_gets) over (),'990.99') pct_bufgets 
from v$sqlarea s
LEFT JOIN dba_hist_sqlstat h ON s.SQL_ID=h.sql_id AND h.parsing_schema_name IN('EREFORM','INTERNET_HOSPITAL')
WHERE s.MODULE='w3wp.exe';
  1. 读磁盘次数 最多的SQL,调整滥用磁盘读操作的主要语句,在绝大多数的系统中,
    访问量占前25位的语句的磁盘读操作将占用整个系统所有磁盘和/或内存读操作的75%。
select disk_reads, substr(sql_text,1,4000) from v$sqlarea  order by disk_reads desc;

二、SQL详细情况分析

WITH BASE_INFO AS (
  SELECT 
    s.SQL_ID,--SQL ID
    s.SQL_FULLTEXT,--完整的sql语句
    s.MODULE,--执行sql的应用程序
    h.action,--包含首次解析SQL语句时执行的操作的名称
    h.SQL_PROFILE,--应用的SQL配置文件的名称
    h.FETCHES_TOTAL,--与SQL语句关联的累计提取数
    h.fetches_delta,--	与SQL语句关联的增量读取数
    h.SORTS_TOTAL,--累计排序数
    h.SORTS_DELTA,--增量排序数
    h.parsing_schema_name,-- SQL执行的用户
    s.PARSE_CALLS,--解析次数,包括软解析和硬解析
    s.EXECUTIONS,--sql执行次数
    s.BUFFER_GETS,--读内存次数
    s.DISK_READS,--读磁盘次数(可以结合读内存次数计算命中率)
    trim(TO_CHAR((s.BUFFER_GETS-s.DISK_READS)/s.BUFFER_GETS,'99999990.999')) Hit_radio,--命中率
		trim(TO_CHAR(s.DISK_READS/s.EXECUTIONS,'99999990.999')) Reads_per_run,--读取率
    trim(TO_CHAR(s.CPU_TIME/1000,'99999990.999')) AS CPU_TIME,--cpu时间,微秒  除1000 后换算成毫秒
    trim(TO_CHAR(s.ELAPSED_TIME/1000,'99999990.999')) AS ELAPSED_TIME,--sql执行时间,微秒 除1000 后换算成毫秒
    s.ELAPSED_TIME/1000 AS ELAPSED_TIME_CALC,
    to_char(s.LAST_ACTIVE_TIME,'YYYY-MM-DD HH24:MI:SS') AS LAST_ACTIVE_TIME, --sql上次的活动时间。
    h.OPTIMIZER_MODE,--执行SQL语句的模式
    h.OPTIMIZER_COST,--优化程序给出的查询成本
    rank() over ( order by buffer_gets desc ) as rank_bufgets,to_char(100 * ratio_to_report(buffer_gets) over (),'990.99') pct_bufgets, --内存使用率
    rank() OVER (order by executions desc) exec_rank, --使用频率
    dense_rank() over(order by disk_reads desc) disk_reads_rank, --消耗磁盘读取数
    dense_rank() over(order by buffer_gets desc) buffer_gets_rank --需要大量缓冲读取数
  FROM v$sqlarea s
  LEFT JOIN dba_hist_sqlstat h ON s.SQL_ID=h.sql_id AND h.parsing_schema_name IN('EREFORM','INTERNET_HOSPITAL')
  WHERE 1=1
    AND s.MODULE='w3wp.exe'--IIS
    AND S.LAST_ACTIVE_TIME BETWEEN TO_DATE('2019-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS') AND SYSDATE--最近3个月
    AND S.ELAPSED_TIME/1000>1000 --大于1秒
)
SELECT T.SQL_ID AS SQLID,
    T.SQL_FULLTEXT AS 完整的SQL语句,
    T.MODULE AS 执行SQL的应用程序,
    T.action AS 解析SQL执行的操作名称,
    T.SQL_PROFILE AS SQL配置文件名称,
    T.FETCHES_TOTAL AS 累计提取数,
    T.fetches_delta AS 增量提取数,
    T.SORTS_TOTAL AS 累计排序数,
    T.SORTS_DELTA AS 增量排序数,
    T.parsing_schema_name AS 执行SQL的用户,
    T.PARSE_CALLS AS 解析次数,
    T.EXECUTIONS AS 执行次数,
    T.BUFFER_GETS AS 读内存次数,
    T.DISK_READS AS 读磁盘次数,
    t.Hit_radio AS 命中率,
    t.Reads_per_run AS 读取率,
    T.CPU_TIME AS CPU时间_毫秒,
    T.ELAPSED_TIME AS SQL执行时长_毫秒,
    T.LAST_ACTIVE_TIME AS 最后执行时间,
    T.OPTIMIZER_MODE AS 执行SQL语句的模式,
    T.OPTIMIZER_COST AS 优化程序给出的查询成本,
    T.pct_bufgets AS 内存使用率,
    t.exec_rank AS 使用频率,
    t.disk_reads_rank AS 消耗磁盘读取数,
    t.buffer_gets_rank AS 需要大量缓冲读取数
FROM BASE_INFO T
ORDER BY T.ELAPSED_TIME_CALC DESC;

三、索引分析

查看用户表空间基本情况

select index_name,table_name,table_owner,tablespace_name,index_type,status  from dba_indexes  where table_owner IN('EREFORM','INTERNET_HOSPITAL');

具体索引分析方法
使用explain plan FOR SELECT SQL具体分析某个比较慢的sql中索引的使用情况

四、表空间分析

查询表空间使用情况

SELECT Upper(F.TABLESPACE_NAME)         "表空间名",
       D.TOT_GROOTTE_MB                 "表空间大小(M)",
       D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空间(M)",
       To_char(Round(( D.TOT_GROOTTE_MB - F.TOTAL_BYTES ) / D.TOT_GROOTTE_MB * 100, 2), '990.99')
       || '%'                           "使用比",
       F.TOTAL_BYTES                    "空闲空间(M)",
       F.MAX_BYTES                      "最大块(M)"
FROM   (SELECT TABLESPACE_NAME,
               Round(Sum(BYTES) / ( 1024 * 1024 ), 2) TOTAL_BYTES,
               Round(Max(BYTES) / ( 1024 * 1024 ), 2) MAX_BYTES
        FROM   SYS.DBA_FREE_SPACE
        GROUP  BY TABLESPACE_NAME) F,
       (SELECT DD.TABLESPACE_NAME,
               Round(Sum(DD.BYTES) / ( 1024 * 1024 ), 2) TOT_GROOTTE_MB
        FROM   SYS.DBA_DATA_FILES DD
        GROUP  BY DD.TABLESPACE_NAME) D
WHERE  D.TABLESPACE_NAME = F.TABLESPACE_NAME
ORDER  BY 1;

查找数据文件指标及路径

select b.file_id  文件ID,
  b.tablespace_name  表空间,
  b.file_name     物理文件名,
  b.bytes/1024/1024       "表空间大小(M)",
  (b.bytes-sum(nvl(a.bytes,0)))/1024/1024   "已使用空间(M)",
  sum(nvl(a.bytes,0))/1024/1024        "剩余空间(M)",
  sum(nvl(a.bytes,0))/(b.bytes)*100 剩余百分比
  from dba_free_space a,dba_data_files b
  where a.file_id=b.file_id AND a.TABLESPACE_NAME='TSP_TEST'
  group by b.tablespace_name,b.file_name,b.file_id,b.bytes
  order by b.tablespace_name;

表空间扩容
方式1:手工改变已存在数据文件的大小

ALTER TABLESPACE TSP_TEST ADD DATAFILE 'D:\APP\ADMINISTRATOR\ORADATA\DERMYY\TSP_TEST.DBF' SIZE 1024M;

方式2:允许已存在的数据文件自动增长

ALTER TABLESPACE TSP_TEST ADD DATAFILE 'D:\APP\ADMINISTRATOR\ORADATA\DERMYY\TSP_TEST.DBF' AUTOEXTEND ON NEXT 100M MAXSIZE 20480M; 

方式3:增加数据文件

ALTER TABLESPACE TSP_TEST ADD DATAFILE 'D:\APP\ADMINISTRATOR\ORADATA\DERMYY\O2_TSP_TEST.DBF' SIZE 100M autoextend on next 100m maxsize unlimited extent management local uniform segment space management AUTO;
ALTER TABLESPACE TSP_TEST ADD DATAFILE 'D:\APP\ADMINISTRATOR\ORADATA\DERMYY\O3_TSP_TEST.DBF' size 100M AUTOEXTEND on next 100m maxsize unlimited extent management local uniform segment space management AUTO;

表空间碎片整理
查看表空间碎片的fsfi值,如果FSFI小于<30则表空间碎片太多.
fsfi的最大可能值为100(一个理想的单文件表空间)。
随着范围的增加,fsfi值缓慢下降,而随着最大范围尺寸的减少,fsfi值会迅速下降

select 
	a.tablespace_name,
	trunc(sqrt(max(blocks)/sum(blocks))* (100/sqrt(sqrt(count(blocks)))),2) AS fsfi 
	from dba_free_space  a,dba_tablespaces b
	where a.tablespace_name=b.tablespace_name
	      and b.contents not in('TEMPORARY','UNDO','SYSAUX')
        AND a.TABLESPACE_NAME='TSP_TEST' AND b.TABLESPACE_NAME='TSP_TEST'
group by A.tablespace_name 
order by fsfi; 

查看dba_free_space
dba_free_space 显示的是有free 空间的tablespace ,如果一个tablespace 的free 空间不连续,
那每段free空间都会在dba_free_space中存在一条记录。如果一个tablespace 有好几条记录,
说明表空间存在碎片,当采用字典管理的表空间碎片超过500就需要对表空间进行碎片整理。

select 
	a.tablespace_name ,
  count(1) 碎片量 
from dba_free_space a, dba_tablespaces b 
where a.tablespace_name =b.tablespace_name AND a.TABLESPACE_NAME='TSP_TEST'
and b.contents not in('TEMPORARY','UNDO','SYSAUX')
group by a.tablespace_name
having count(1) >20
order by 2;

查看表空间碎片整理方法

alter tablespace 表空间名 coalesce;

如果再次查看碎片没有减少,则需考虑重建表空间。

你可能感兴趣的:(#,ORACLE,sql,oracle,数据库)