`
mikixiyou
  • 浏览: 1098771 次
  • 性别: Icon_minigender_1
  • 来自: 南京
博客专栏
C3c8d188-c0ab-3396-821d-b68331e21226
Oracle管理和开发
浏览量:353091
社区版块
存档分类
最新评论

参数cursor_sharing的设置导致含占位符的SQL执行变慢问题

阅读更多

我们的应用程序开发人员发现这样一个异常现象,某 SQL 语句在使用绑定变量时,执行的时间比不使用绑定变量时要慢很多,甚至慢到数十倍。

在应用程序中,执行的 SQL 如果没有绑定变量,那么可能会导致共享池挣用等待事件的出项。而且,这种情况在很多应用系统的程序开发中很常见。对此, Oracle 数据库系统提供了一种折中解决方法,将初始化参数 cursor_sharing 的值设置为 force similar 。这样,在 Oracle 中运行的 SQL ,其常量如字符、数字等则会自动转换为变量,从而使得类似 SQL 变得一样,减少共享池挣用。

在出现该问题的数据库系统中,它的初始化参数 cursor_sharing 的值是 force

从问题现象看,使用绑定变量的 SQL 执行计划和不使用绑定变量的不一样,前者走的执行计划不合理。

这个 SQL 也比较复杂, where 子句中既有自定义的变量语句,也有很多常量语句。在常量条件中,有个占位符子句,紧随 where 关键字。

这类写法在 JAVA 中拼装 SQL 语句时很常见。在需要新加条件判断语句时,直接加上 ”and xx=yy” ,变成 ”where 1=1 and xx=yy”

这种写法很通用吧?

(miki西游 @mikixiyou 的文档,原文链接: http://mikixiyou.iteye.com/blog/1552021

语句

出现问题的 SQL 语句如下:

SELECT *

   FROM (SELECT row_.*, ROWNUM rownum_

           FROM (select count(*)

                   from (select t1.id as id,

                                'sms' as type,

                                t1.empid as empid,

                                t1.deptno as deptno,

                                t1.content as title,

                                to_char(t1.send_time, 'yyyy-MM-dd hh24:mi:ss') as plantime,

                                t1.sysuid as sysuid,

                                t1.custid as custid,

                                t1.mobile as contact,

                                t1.mark as mark

                           from liantong_send_back t1

                          where 1 = 1

                            and t1.send_time >=

                                to_date('2011-11-01 00:00:00',

                                        'yyyy-mm-dd hh24:mi:ss')

                            and t1.send_time <

                                (to_date('2011-12-06 00:00:00',

                                         'yyyy-mm-dd hh24:mi:ss') + 1)

                            and t1.deptno = '3400'

                         union all

                         select t1.id as id,

                                'sms' as type,

                                t1.empid as empid,

                                t1.deptno as deptno,

                                t1.content as title,

                                to_char(t1.send_time, 'yyyy-MM-dd hh24:mi:ss') as plantime,

                                t1.sysuid as sysuid,

                                t1.custid as custid,

                                t1.mobile as contact,

                                t1.mark as mark

                           from liantong_send t1

                          where 1 = 1

                            and t1.send_time >=

                                to_date('2011-11-01 00:00:00',

                                        'yyyy-mm-dd hh24:mi:ss')

                            and t1.send_time <

                                (to_date('2011-12-06 00:00:00',

                                         'yyyy-mm-dd hh24:mi:ss') + 1)

                            and t1.deptno = '3400') T

                  where rownum < 10001

                  order by T.plantime desc, T.id) row_

          WHERE ROWNUM <= :b)

 WHERE rownum_ > :a

这个 SQL 的内部 where 条件中有一个“ 1=1 ”的条件,这是开发人员在条件不定时,动态添加条件的常用写法。这种写法在很多类型的应用中都出现过。

这个 SQL 很明显去掉 rownum 的条件判断使用的绑定变量,其他条件都是常量赋值。这是因为内部那个结果集的 SQL 是应用程序拼出来的,条件很灵活,不容易实现带变量的写法。因此我们让数据库系统在执行之前自动去修改这些常量为变量,从而实现不同常量的 SQL 能共享游标( cursor ),减少硬分析。

设置 cursor_sharing=force ,就实现了这种自动转换。但占位符(“ 1=1 ”)也会被系统自动替换成 :"SYS_B_02" = :"SYS_B_03"

但在 cursor_sharing=exact 时,系统的优化器则是做了另一种操作。它将占位符(“ 1=1 ”)忽略掉,因为也确实不需要去判断,从而节省 CPU 执行时间。很聪明吧!

分析

我先做了一些简单的测试:

测试一、将 SQL 中设置的变量取消,让 SQL 完全由系统生成绑定变量,语句执行正常;

测试二、将 cursor_sharing 修改成默认值( exact ), SQL 使用绑定变量,语句执行也是正常;

测试三、将 SQL 中占位符 (“1=1”) 去掉,应用使用绑定变量, cursor_sharing 设置为 force ,语句执行也正常。

 

测试结果显示,如果没有占位符,就正常了。

这是怎么回事呢?

看来,必须去他们各自的分析执行计划才能明白了。

 

--待续

分享到:
评论

相关推荐

    oracle 参数详解

    Oracle的CURSOR_SHARING参数是数据库性能优化中的一个重要设置,它决定了SQL语句在什么情况下可以共享相同的游标(cursor)。游标在Oracle数据库中扮演着关键角色,它们是执行查询时保存信息的结构,包括关于如何从...

    SQL2BIND-VARIABLE

    如果不能使用强制绑定变量的oracle 参数 cursor_sharing=force ,也不能用触发器修改某个用户的 cursor_sharing=force 会话参数,那么这个转换程序可以帮到你(不能解决使用JAVA等编程语言,因为java使用?占位符不...

    set_cursor_pos_SetCursorPos_Set-Cursor-Position_

    如果函数执行成功,尽管返回值为 `TRUE`,但并不意味着鼠标位置实际上已经改变,因为用户可能在函数执行期间移动了鼠标,或者由于权限问题无法改变鼠标位置。 在LabVIEW环境中,`set_cursor_pos.vi` 可能是一个封装...

    通过分析SQL语句的执行计划优化SQL

    5. **CURSOR_SHARING设置**:合理设置CURSOR_SHARING参数可以帮助数据库更好地共享相同的执行计划,进一步提高查询效率。 #### 示例解析 以Oracle数据库为例,下面将通过几个具体示例来进一步解释上述概念: 1. *...

    oracle-cursor.rar_cursor_oracle_oracle cursor

    FETCH cursor_name INTO variable1, variable2; ``` - 处理:根据需要对提取的数据进行处理。 - 关闭:使用CLOSE语句关闭游标,释放资源。 ```sql CLOSE cursor_name; ``` 4. 游标属性 Oracle游标有一些关键属性,...

    使用Python防止SQL注入攻击的实现示例

    在这个例子中,`%s`是一个占位符,代表查询参数。通过将参数传递给`execute()`方法的第二个参数,可以确保输入被正确转义,不会被解析为SQL命令的一部分。 #### 四、总结 本文详细介绍了如何使用Python防止SQL注入...

    Oracle动态执行SQL四种方式的例子

    在Oracle数据库管理中,动态执行SQL语句是一种强大的功能,允许开发者在运行时构建和执行SQL语句,这对于处理不确定或变化的数据结构尤其有用。本文将深入探讨Oracle中动态执行SQL的四种主要方法,并通过具体示例...

    007_insert_seal_approval_cursor.sql

    007_insert_seal_approval_cursor.sql

    通过分析SQL语句的执行计划优化SQL.doc

    硬编码SQL由于列值的不同导致无法共享执行计划,而CURSOR_SHARING参数可以通过设置,让数据库在一定程度上接受列值变化但结构相同的SQL作为共享SQL,从而提高效率。 总的来说,分析SQL语句的执行计划涉及多个层面,...

    DBMS_SQL的使用

    在这个例子中,我们定义了一个过程`define_column`,该过程接受一个数字参数`no`,并根据这个参数执行SQL查询(`SELECT * FROM demo WHERE a = :no`)。这里使用了`define_column`方法来指定结果集中第二列的数据...

    Python填充SQL参数脚本.zip

    这个名为"Python填充SQL参数脚本.zip"的压缩包提供了一个解决方案,旨在解决一个常见的问题:手动替换SQL查询中的占位符(通常是问号'?')以适应实际的数据。在服务器日志中,我们经常发现SQL语句被记录下来,但为了...

    OracleSql规则与优化

    最后,我们还可以通过设置`cursor_sharing`参数实现服务器端的变量绑定策略。`cursor_sharing=force`强制所有的绑定变量都被视为相同,`cursor_sharing=exact`则根据变量的实际值创建独立的游标,而`cursor_sharing=...

    use_default_cursor.rar_-use_cursor_DEMO

    在本DEMO中,"use_cursor_DEMO"可能包含了以下内容: 1. **代码示例**:DEMO可能包含了一段使用预定义光标的代码,展示了如何在程序中打开、遍历和关闭游标。例如,在Python的DB-API中,可以使用`cursor.execute()`...

    oracle执行计划详解

    从 Oracle 8i 开始,新引入了 CURSOR_SHARING 参数,该参数的主要目的就是为了解决在编程过程中已大量使用的硬编码 SQL 问题。 Oracle 执行计划是 Oracle 数据库性能调整的关键部分,了解这些背景知识和重要概念...

    ORACLE8 PLSQL程序设计_sql_code.zip_oracle pl/sql_pl sql code_pl/sql_

    2. **debug**: 09-DEBUG.PC可能包含了调试PL/SQL代码的技巧和示例,这对于解决程序中的错误和性能问题至关重要。 3. **RSINS**: "RSINS"可能是"Row Source Insertion"的缩写,09-RSINS.PC可能涉及到在PL/SQL中插入...

    oracle执行动态sql

    ### Oracle 执行动态 SQL 的几种方法 在数据库管理和应用程序开发中,经常需要处理不固定、不可预知的数据查询和更新需求。此时,静态 SQL(即硬编码的 SQL 语句)无法满足这些灵活多变的需求,这就需要使用动态 ...

    SQL SERVER python.rar_python SQL Server_python sql server_pytho

    Python还支持使用参数化查询来防止SQL注入攻击,如下所示: ```python id_to_find = 123 sql_query = "SELECT * FROM your_table_name WHERE id = ?" cursor.execute(sql_query, (id_to_find,)) row = cursor....

    ORACLE数据库使用动态SQL的方法.pdf

    DBMS_SQL.PARSE(cursor_id, 'SELECT * FROM table', DBMS_SQL.NATIVE); DBMS_SQL.DEFINE_COLUMN(cursor_id, 1, col_name); DBMS_SQL.EXECUTE(cursor_id); LOOP EXIT WHEN DBMS_SQL.FETCH_ROWS(cursor_id) = 0; ...

    pl_sql基本语法例子.rar_SQL2569_oracle_pl/sql_plsql增删改查

    存储过程是一组PL/SQL语句,可以接受参数,执行一系列操作并返回结果。函数与存储过程类似,但必须返回一个值。创建存储过程和函数的语法涉及PROCEDURE和FUNCTION关键字,以及IN、OUT、IN OUT参数类型。 7. 触发器...

    ORACLE的执行计划[参照].pdf

    通过设置CURSOR_SHARING参数,可以强制Oracle将某些具有相同结构但列值不同的SQL语句视为相同,从而提高性能。 总的来说,理解Oracle的执行计划和共享SQL语句的概念对于优化数据库性能至关重要。通过合理配置数据库...

Global site tag (gtag.js) - Google Analytics