oracle

检查绑定变量

2018-03-01  本文已影响0人  若有所思11

在Oracle数据库里 如果SQL 语句的条件值没有使用绑定变量的话,会导致数据库的CPU使用率很高!
这个该怎么理解呢? 因为每个SQL语句 相对于是个函数,条件值就是实际上的实在参数.

比如说 CALLME(IPHONE_NUMBER :NUMBER);

在C语言里函数有形参和实参两个概念.
IPHONE_NUMBER 就是形参
调用的时候 CALLME(13556876091); 这个电话号码就是实参.

每个SQL语句 跟函数是一样的. 应用程序向数据库发布一条SQL语句,
如果这个SQL语句是实参的形式:

SELECT *
FROM CUSTOR
WHERE IPHONE_NUMBER=13556876091;

那么它就无法形成函数方式. 会变成内联方式. 跟C 语言的INLINE .
就会函数的代码展开插入到调用代码当中. 这样就会形成代码的臃肿.
在C语言是一次性编译的.所以就确定了有多少调用函数的地方,就把它插入进去.

而SQL语句 是解释型的 每运行一次都要解释下,就是把字符编码转换成二进制编码.
如果把SQL语句 做成函数模式的话, 那就不用解释多次了.如同C语言函数样编译一次 保留在代码里. ORACLE就把它保留在内存中.SGA里的共享池里的代码区.

另外一个特点就不会臃肿了,就是数据库内存不会占用太多了.
要知道 数据库是提供服务的,鬼知道一天下来有多少次请求,尤其相同的SQL语句,不同的电话号码啊! 每次都要编译一次,每次都要分配内存给它.

累不? 当然累啊.

SELECT FORCE_MATCHING_SIGNATURE,to_char(FORCE_MATCHING_SIGNATURE ) as sing,

       COUNT(1) AS REPLACE_NUM,

       ROUND(SUM(SHARABLE_MEM) / 1024 / 1024) AS SHARED_MB,

       ROUND(SUM(PERSISTENT_MEM) / 1024 / 1024) AS PERSISTENT_MB,

       ROUND(SUM(RUNTIME_MEM) / 1024 / 1024) AS RUNTIME_MB,

       ROUND(SUM(CPU_TIME) / SUM(EXECUTIONS) / 1000, 3) AS CPU_TIME_AS_HAO,

       ROUND(SUM(ELAPSED_TIME) / SUM(EXECUTIONS) / 1000, 3) AS ELAPSED_TIME_AS_HAO

  FROM V$SQL

 WHERE FORCE_MATCHING_SIGNATURE > 0

   AND EXECUTIONS > 0

   AND FORCE_MATCHING_SIGNATURE != EXACT_MATCHING_SIGNATURE

 GROUP BY FORCE_MATCHING_SIGNATURE

HAVING COUNT(1) > 1

 ORDER BY 2 DESC;

这个SQL 是查出哪些语句 是重复性的.

FORCE_MATCHING_SIGNATURE    SING    REPLACE_NUM RUNTIME_MB  PERSISTENT_MB   SHARED_MB   CPU_TIME_AS_HAO ELAPSED_TIME_AS_HAO

8.6982391179123E18  8698239117912304505 18  1   0   0   1.111   1.329

8.75852822924708E18 8758528229247075989 9   0   0   0   1.778   14.441

列说明

FORCE_MATCHING_SIGNATURE            --匹配编码

SING                                                            --非科学匹配编码

REPLACE_NUM                                        --重复语句条数

SHARED_MB                                                  --共享内存

PERSISTENT_MB                                          --持久内存       

RUNTIME_MB                                        --运行内存

CPU_TIME_AS_HAO                               --CPU消耗时间毫秒

ELAPSED_TIME_AS_HAO                          --整天消耗时间毫秒

拿 8698239117912304505 这个数再去查是谁

SELECT X.*

  FROM V$SQL X

 WHERE FORCE_MATCHING_SIGNATURE IN ('&SIGNATURE') ;

得到结果:

SQL_ID  SQL_TEXT

dxvw27pbcn1kn   UPDATE traderecord t WHERE t.tr_no ='2016090217185977218913' 

dn7b81pzcw86m   UPDATE traderecord t WHERE t.tr_no ='2016090216072767533038' 

3bs4f6jmu0hgy   UPDATE traderecord t WHERE t.tr_no ='2016090715060677358642' 

41a6jfwdu0jau   UPDATE traderecord t WHERE t.tr_no ='2016090217301151535871' 

9jx4x1yr4tznb   UPDATE traderecord t WHERE t.tr_no ='2016090619560633407255' 

4gxz4k4vku5q1   UPDATE traderecord t WHERE t.tr_no ='2016090619501112421155' 

7s2cc5zkhk6vd   UPDATE traderecord t WHERE t.tr_no ='2016090217230866411499' 

76qy6jrhkk9js   UPDATE traderecord t WHERE t.tr_no ='2016090619541287847558' 

736vanbstqbth   UPDATE traderecord t WHERE t.tr_no ='2016090216352375392201' 

akux5jq8tqh84   UPDATE traderecord t WHERE t.tr_no ='2016090715204060248022' 

1zdg5hnypkmg8   UPDATE traderecord t WHERE t.tr_no ='2016090217292254067007' 

4d0m7bjrcqtya   UPDATE traderecord t WHERE t.tr_no ='2016090216354359471268' 

23px2h297uzf1   UPDATE traderecord t WHERE t.tr_no ='2016090217234737101115' 

cv47h8181m273   UPDATE traderecord t WHERE t.tr_no ='2016090216080006730705' 

gj3suh2h4g350   UPDATE traderecord t WHERE t.tr_no ='2016090620045611126149' 

b934afb823nv3   UPDATE traderecord t WHERE t.tr_no ='2016090217141794421678' 

9fk19gy3dbrhj   UPDATE traderecord t WHERE t.tr_no ='2016090616481995859489' 

6yqgrd7u9rz63   UPDATE traderecord t WHERE t.tr_no ='2016090619322020607209' 

可以看出来 T.TR_NO=没有使用绑定变量

总结:

(1)对于OLTP系统,相同的SQL重复频率非常高,如果优化器反复解析SQL,必然会极大的消耗系统资源,另外,OLTP系统用户请求的结果集都非常小,所以基本上都考虑使用索引。 Bind Peeking 在第一次获得了一个正确的执行计划之后,后续的所有SQL都按照这个执行计划来执行,这样就极大的改善了系统的性能。
(2)对于OLAP系统,SQL执行计划和谓词关系极大,谓词值不同,可能执行计划就不同,如果采用相同的执行计划,SQL的执行效率必然很低。另外,一个OLAP系统数据库每天执行的SQL数量远远比OLTP少,并且SQL重复频率也远远低于OLTP系统,在这种条件下,SQL解析花费的代价和SQL执行花费的代价相比,解析的代价可以完全忽略。
(3)所以,对于OLAP系统,不需要绑定变量,如果使用可能导致执行计划选择错误。 并且,如果用了绑定变量,Bind Peeking也只能保证第一条硬分析SQL能正确的选择执行计划,如果后面的谓词改变,很可能还是会选择错误的执行计划。 因此在OLAP系统中,不建议使用绑定变量。

检查语句

WITH c AS
  (SELECT FORCE_MATCHING_SIGNATURE, COUNT(*) cnt
     FROM v$sqlarea
    WHERE FORCE_MATCHING_SIGNATURE != 0
    GROUP BY FORCE_MATCHING_SIGNATURE
   HAVING COUNT(*) > 20),
 sq AS
  (SELECT sql_id,
          FORCE_MATCHING_SIGNATURE,
          row_number() over(partition BY FORCE_MATCHING_SIGNATURE ORDER BY sql_id DESC) p
     FROM v$sqlarea s
    WHERE FORCE_MATCHING_SIGNATURE IN
          (SELECT FORCE_MATCHING_SIGNATURE FROM c))
 SELECT sq.sql_id, sq.FORCE_MATCHING_SIGNATURE, c.cnt "unshared count"
   FROM c, sq
  WHERE sq.FORCE_MATCHING_SIGNATURE = c.FORCE_MATCHING_SIGNATURE
    AND sq.p = 1
  ORDER BY c.cnt DESC

转载:http://mp.weixin.qq.com/s?__biz=MzIxMTQ5NjMzNQ==&mid=2247483768&idx=1&sn=f4aa0ed2ae5b51521e3c51b17e55fcb9&scene=0#wechat_redirect

上一篇下一篇

猜你喜欢

热点阅读