`
liwenshui322
  • 浏览: 520581 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Oracle 游标与绑定变量

 
阅读更多

 

oracle执行SQL语句就是打开游标,解析游标,执行游标,关闭游标的过程。了解游标的这几个阶段,我们也就弄清楚了SQL执行过程,这是本文要介绍的第一个内容。另外,在java编程中,我们通常说要使用预处理的形式来写SQL语句(比如:select  * from table where A = ?),也就是绑定变量的形式。因为,这样效率高。那么,为什么使用绑定变量就比不使用绑定变量(比如:select * from table where A = '123')要效率高呢?这是本文要介绍的第二个内容。


        一. 游标的生命周期

       一条sql语句的执行过程,就是一个游标的生命周期。如下图所示:


     1. 打开游标:系统为这个游标分配一个内存结构。

        2. 解析游标:将一条SQL与这个游标关联。解析这条sql语句,将解析的结果加载到共享池中。

        3. 定义输出变量:如果这条SQL返回数据,先定义接收数据的变量。

        4. 定义输入变量:如果SQL语句使用了绑定变量,提供他们的值。

        5. 执行游标:执行SQL语句。

        6. 获取游标:如果SQL语句有返回数据,接收返回的数据。

        7. 关闭游标:释放第一步分配的内存,供其他游标使用,但是第二步解析的SQL结果(也就是共享游标)不会被释放,以期待被重新使用。


        我们可以通过一段PL/SQL代码来看一下游标的这几个步骤:      


  1. DECLARE  
  2.   l_ename emp.ename%TYPE := 'SCOTT';  
  3.   l_empno emp.empno%TYPE;  
  4.   l_cursor INTEGER;  
  5.   l_retval INTEGER;  
  6. BEGIN  
  7.   l_cursor := dbms_sql.open_cursor; /*打开游标*/  
  8.   dbms_sql.parse(l_cursor, 'SELECT empno FROM emp WHERE ename = :ename', 1); /*解析游标*/  
  9.   dbms_sql.define_column(l_cursor, 1, l_empno); /*定义输出变量*/  
  10.   dbms_sql.bind_variable(l_cursor, ':ename', l_ename); /*定义输入变量*/  
  11.   l_retval := dbms_sql.execute(l_cursor); /*执行游标*/  
  12.   IF dbms_sql.fetch_rows(l_cursor) > 0  /*获取游标*/  
  13.   THEN    
  14.     dbms_sql.column_value(l_cursor, 1, l_empno);  
  15.     dbms_output.put_line(l_empno);  
  16.   END IF;  
  17.   dbms_sql.close_cursor(l_cursor); /*关闭游标*/  
  18. END;  


 

        二. 游标的解析过程

       在游标的这几个过程中,我们唯一能影响的就是解析过程。解析过程的快与慢,与我们写的sql语句有直接关系。那么游标的解析过程(也就是SQL的解析过程)是怎样的呢?看下图:


       1. 包含VPD的约束条件检查:如果系统中使用了虚拟私有数据库,并且被解析的SQL语句中引用的某张表激活了它的话,安全策略生成的约束条件会被添加到where条件中(说实话,这个我也没看懂,先不管)

       2. 语法,语义以及访问权限检查:就是检查我们写的SQL写得对不对,引用的表是否存在等。

       3. 将父游标保存到库缓存:如果没有找到共享的父游标,就会在库缓存中缓存这个父游标。父游标保存的是这条SQL的文本信息,今后如果重新执行这条SQL语句,这个父游标是可以重用的。

       4. 逻辑优化与物理优化:生成这条SQL所有可能的执行计划,然后根据执行计划的开销,选择开销最小的一条执行计划。

       5. 将子游标保存到库缓存:上一步选择的最优执行计划信息和当前的执行环境,会当做子游标的信息保存到库缓存,并与父游标关联。


       总之,父游标保存的是SQL文本信息,今后可以被重用。子游标保存的是当前执行环境下所选择的这条SQL最优的执行计划,如果父游标被重用,执行环境没变,那么子游标也会被重用。

       当父游标和子游标都可重用,那么只需要执行前2步,此时对应的解析称为软解析。如果父游标与子游标都不可重用,所有的步骤都执行的时候,就是我们说的硬解析。因为硬解析里面的逻辑优化与物理优化是非常依赖cpu的操作,所以硬解析相对而言是比较耗时的。也就是我们为什么说要尽可能避免硬解析。


       三. 绑定变量优点

       绑定变量可以有效消除硬解析,我们执行如下一段SQL文本:


  1. DROP TABLE t;  
  2.   
  3. CREATE TABLE t (n NUMBER, v VARCHAR2(4000));  
  4.   
  5. ALTER SYSTEM FLUSH SHARED_POOL;  
  6.   
  7. VARIABLE n NUMBER  
  8. VARIABLE v VARCHAR2(32)  
  9.   
  10. EXECUTE :n := 1; :v := 'Helicon';  
  11.   
  12. INSERT INTO t (n, v) VALUES (:n, :v);  
  13.   
  14. EXECUTE :n := 2; :v := 'Trantor';  
  15.   
  16. INSERT INTO t (n, v) VALUES (:n, :v);  
  17.   
  18. EXECUTE :n := 3; :v := 'Kalgan';  
  19.   
  20. INSERT INTO t (n, v) VALUES (:n, :v);  
  21.   
  22. SELECT sql_id, child_number, executions  
  23. FROM v$sql  
  24. WHERE sql_text = 'INSERT INTO t (n, v) VALUES (:n, :v)';  
  25.   
  26. drop table t;  

        我们会发现最后一个select语句执行的结果如下图所示:


 

     说明对应这条insert语句只生成了一个父游标,只是这个父游标被执行了3次。也就是除开第一次插入的时候,我们进行了硬解析。接下来2次,我们都进行的是软解析。


       四. 绑定变量缺点

       影响oracle选择效率低下的执行计划。

       由于使用绑定变量,父游标和子游标都能共享重用(除开第一次硬解析,其他每次都是软解析)。子游标每次都重用(除开第一次),那么执行计划每一次都相同。假如子游标里面的执行计划确认进行的是全表扫描,因为第一次要查询这个表里面绝大部分数据,oracle认为执行全表扫描快。如果第二次只需要扫描很小一部分数据,执行索引扫描比较快的话。由于子游标重用,还执行的是全表扫描。我们可以看一个例子:

      执行如下一段SQL文本:


  1. VARIABLE id NUMBER  
  2. SET ECHO ON  
  3. ALTER SYSTEM FLUSH SHARED_POOL;  
  4. DROP TABLE t;  
  5. CREATE TABLE t   
  6. AS   
  7. SELECT rownum AS id, rpad('*',100,'*'AS pad   
  8. FROM dual  
  9. CONNECT BY level <= 1000;  
  10.   
  11. ALTER TABLE t ADD CONSTRAINT t_pk PRIMARY KEY (id);  
  12.   
  13. BEGIN  
  14.   dbms_stats.gather_table_stats(  
  15.     ownname          => user,   
  16.     tabname          => 't',   
  17.     estimate_percent => 100,   
  18.     method_opt       => 'for all columns size 1'  
  19.   );  
  20. END;  
  21. /  
  22.   
  23. EXECUTE :id := 990;  
  24. SELECT count(pad) FROM t WHERE id < :id;  
  25. SELECT * FROM table(dbms_xplan.display_cursor(NULLNULL'basic'));  
  26. EXECUTE :id := 10;  
  27. SELECT count(pad) FROM t WHERE id < :id;  
  28. SELECT * FROM table(dbms_xplan.display_cursor(NULLNULL'basic'));  

       我们发现当 id=10, 也就是查询非常小部分数据的时候,仍然执行的是全表扫描,如下图:


       

       五. 绑定变量使用场景

       什么时候应该使用绑定变量,什么时候又应该避免呢?

       我们可以看到,使用绑定变量主要是为了避免硬解析,也就是加快SQL的解析时间,但是有可能导致Oracle重用效率低下的执行计划。也就是延长SQL的执行时间。这个时候我们应该权衡,这条SQL是解析时间比较长还是执行时间。

       1. 如果一次只处理小部分数据,解析时间等于或者高于执行时间,那么建议使用绑定变量。

       2. 如果一次处理大批量数据,执行时间高于解析时间几个数量级,那么没必要使用绑定变量,加快那么一点解析时间微不足道。而且还有可能导致oracle重用效率低下的执行计划,大大影响SQL的执行速度。

  • 大小: 117.9 KB
  • 大小: 3.8 KB
  • 大小: 14.4 KB
  • 大小: 107.8 KB
分享到:
评论

相关推荐

    Oracle游标使用案例大全

    Oracle游标是数据库编程中非常重要的一个概念,主要用于处理SQL查询的结果集。游标允许我们按行处理数据,逐条读取结果集,而不仅仅是一次性获取所有数据。在Oracle数据库中,游标对于复杂的事务处理、动态SQL以及...

    Oracle数据库的绑定变量特性及应用.pdf

    Oracle数据库的绑定变量是一种优化策略,它在提升数据库性能、可扩展性和稳定性方面扮演着重要角色。绑定变量的使用能够显著改善SQL语句的执行效率,尤其是在处理大量重复查询时。本文将深入探讨绑定变量的原理、...

    Oracle游标的使用方法.pdf

    - **打开游标**:使用`OPEN`语句打开已声明的游标,这会基于绑定变量的值确定活动集,并将指针指向第一行。 ```sql OPEN cursor_name; ``` - **提取结果**:使用`FETCH`语句将查询结果提取到PL/SQL变量中。有两...

    oracle游标溢出调优

    而 `FORCE` 则强制所有SQL语句都使用绑定变量,进一步减少解析次数。 此外,还有几个相关的视图用于监控游标状态: - `V$OPEN_CURSOR` 显示每个用户会话当前打开并解析的游标信息。 - `V$SQLAREA` 提供关于共享SQL...

    Oracle游标语法总结.doc

    打开游标(OPEN),解析,绑定,不会从数据库检索数据 - 从游标中获取记录(FETCH INTO),执行查询,返回结果集,通常定义局域变量作为从游标获取数据的缓冲区 - 关闭游标(CLOSE),完成游标处理,用户不能从...

    Oracle 游标的使用

    在Oracle 9i及其以后的版本中,还增加了使用BULK COLLECT子句批量绑定数据和使用CURSOR表达式实现嵌套游标的功能。本章将主要介绍如何使用显式游标进行多行数据的查询、游标FOR循环以及游标变量的使用,另外还将介绍...

    第十四课Oracle游标和异常处理.pptx

    Oracle数据库系统中,游标和异常处理是两个关键概念,特别是在复杂的数据库操作和程序设计中。游标允许我们逐行处理查询结果,而异常处理则提供了错误管理的机制,确保程序在遇到错误时能优雅地恢复或终止。 首先,...

    oracle 游标,存储过程,SQL优化的总结

    优化策略包括但不限于:使用合适的索引,避免全表扫描,减少子查询,使用JOIN代替子查询,合理使用绑定变量,以及优化数据类型选择等。此外,Oracle还提供了许多内置的工具,如Explain Plan和SQL Trace,帮助开发者...

    sql绑定变量

    标题与描述中的“SQL绑定变量”这一知识点,主要聚焦于SQL语句中如何使用变量,尤其是在存储过程或函数中动态构建SQL语句时的关键技术。绑定变量允许在SQL语句中使用程序变量作为参数,这不仅提高了代码的可读性和...

    Oracle数据库的游标学习总结

    Oracle游标主要分为两大类:显示游标和隐式游标。其中,显示游标又可以根据定义方式的不同细分为静态游标和动态游标。 ##### 显示游标 显示游标主要用于处理SELECT语句的结果集。当定义游标时,需要明确指定SQL...

    批量插入数据到Oracle数据库Demo

    4. **绑定变量**:在Oracle中,绑定变量可以用来提高查询性能,减少解析次数。在批量插入时,可以使用绑定变量来存储多个值,然后在INSERT语句中重复使用。 5. **游标(Cursor)**:游标是处理结果集的有效工具,...

    ORACLE练习题ORACLE练习题

    3. SQL优化:分析慢查询,使用EXPLAIN PLAN理解执行计划,通过绑定变量、物化视图、索引覆盖等方式优化查询性能。 4. 表空间设计:根据数据量和访问模式设计合理的表空间策略,如使用分区、分段等技术。 5. 内存管理...

    Oracle数据库游标连接超出解决方案

    - 使用绑定变量:绑定变量可以重用SQL语句的解析计划,减少游标开销。 - 减少显式游标使用:尽可能使用数据库提供的隐式游标,它们通常更高效且易于管理。 - 分析SQL性能:通过`V$SQL`视图分析SQL语句的执行情况...

    Latch Free、Library cache伪游标(pseudo cursor)之间的那些事

    3. 优化应用程序中SQL硬解析的频率,例如通过绑定变量来避免不必要的硬解析。 4. 分析v$librarycache视图中的数据,找出那些频繁被重新加载的对象,并考虑修改应用程序逻辑以减少其影响。 5. 考虑使用Oracle的自动...

    Oracle面试题

    1. **Oracle游标**: - 游标允许我们处理查询结果集中的一行数据,分为显示游标和隐式游标。 - 显示游标通过`cursor...is`语句定义,可以显式管理和控制查询结果集,适用于处理多条记录。 - 隐式游标则是由PL/SQL...

    父子游标详解[收集].pdf

    父子游标详解 父子游标是 Oracle 中的一种机制,用于优化 SQL 语句的执行。它通过共享游标来减少开销,提高系统性能。...但是,软解析和硬解析需要根据实际情况进行选择,绑定变量和优化器也需要仔细斟酌。

    《精通Oracle 10g Pro*C/C++编程》源代码与学习笔记

    3. **游标和绑定变量**:游标是Oracle中的一个关键概念,用于处理结果集。Pro*C中使用游标来逐行处理查询结果,而绑定变量则用于在SQL语句中传递参数,提高性能并减少SQL注入的风险。 4. **异常处理**:Oracle提供...

    cx-oracle英文原版.pdf

    - 讨论了绑定变量的使用,包括按名称或位置绑定参数,绑定方向,绑定NULL值,ROWID值,DML RETURNING绑定变量,LOB绑定变量,REF游标绑定变量,以及如何绑定PL/SQL集合和记录。 ### 结论 文档内容涉及了cx_Oracle...

    oracle 执行计划 详解

    为了优化执行计划,我们可以使用绑定变量、减少硬解析、配置 session_cached_cursors、高速缓存游标等方法。 绑定变量 使用绑定变量可以减少硬解析的数量。例如,在 SQL 语句中使用绑定变量 `:empno` 代替硬编码的...

Global site tag (gtag.js) - Google Analytics