检查绑定变量
在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