2022年父子游标详解 .pdf
当 Client 与 Server Process建立了 连接, 构成一次 会话 session之后。客 户端就可以 输入SQL 语句, 对数据 库数据进行操作了。2、解析 SQL,执行操作SQL 语句是描述性 语句。我 们使用 SQL 的 时候,只是去描述我们需要 数据的特征,而不是确定 数据获取的 执 行方法。任何一 条 SQL 语句执行,都是通 过解析、 执 行和 获取三 个主要步 骤,若干 个子步 骤组 成。解析 parse 任何 SQL 语 句,在 Oracle 环境下都是 处理为游标 cursor 。对 SQL 语句的 处理, 实际上就是对 cursor 的 处理。Oracle 处理 SQL 语句,首先要 检查 SGA 区中的 shared pool子区,看里面是否存在相同SQL 的父游 标子游 标。查询 的依据, 就是 SQL 语句本身(以及其hash 值生成的sql_id )。每一 个在 Oracle 中执行的 SQL 语句,都需要在shared pool中建立一 个父游标和子游 标的对。父游 标对应 的是所有相同SQL 语句的游 标, 都可以共享 该父游标。 在同一 个父游 标下,允许 有多 个子游 标 , 他们表示 SQL 语句在不同 执行用 户、 不同 优化器模式和 环境等因素下,对应 的不同的 执行 计划 。SQL 在 Share Pool中寻 找的共享 Cursor , 就是 寻找相同的子游标项(前提肯定是在sql_id已经一样就是说父游标已经共享了),目的是 为了共用 执行计划 。软解析:一条 SQL 语 句, 通 过语 法检查 后。 如果可以在shared pool中寻找到可共享的子游标对象,就可以 实现执 行计划 的共享。 这个过 程,我们称为软 解析。 找到相同的父游标是不够的,要找到相同的子游标才行,父游标表示的就是sql text一直,子游标代表了要考虑到执行环境优化器模式不同用户等,能共享子游标才能进行软解析,当然这个前提是父游标已经可以共享了,也就是说最终的意思是达到共享父子游标。硬解析:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 5 页 - - - - - - - - - 如果 没有在 shared pool中寻找到相同可共享的游标记录 。那么,首先向 实例申请,要求SGA 中分配空 间和资源, 进行 SQL 语 句的分析解析工作。这部分通常需要分配内存空 间,以装 载生成的父子游 标记录 。我 们称这个过 程为硬解析。相对 于软解析, 硬解析需要消耗更多的系统资 源。更重要的是,在 进行硬解析的 过程中, 对SQL 涉及到的 数 据库对 象,可能都有 锁或者 latch 的操作。 这样 是不利于 实现多用 户并发 的数据 库系统的。所以,一般我们都 尽量避免硬解析,尽可能实现 游标共享。当然, 软解析也不是 绝对 完美的 选择 。在一些高 并发 、高处理量的系 统中,绝对 的游 标共享也是可能引起性能瓶颈 的。所以,一些时候还要人 为避免 软解析的 发生。实现 游标共享的最常用 技术就是 绑 定变量,通 过绑 定变量,可以 实现类 似业务操作 SQL 的共享。也就是一 种软 解析技 术。 但是,绑定变量最大的 问题 也就是 peeking , 在实际 系统中,也是要仔 细区别 斟酌的。对 SQL 语句的解析后, Oracle 要使用 优 化器生成 对应 的执行计划。目前,最常用的就是CBO(基于成本的 优 化器)。优化器的原理比较复杂 ,是 Oracle 核心技 术之一。简单 的说,Oracle 会用不同的方法 (自 动收集、 作业脚本) ,收集数据表、索引的 统计信息, 作为 CBO工作的依据。之后,对一个 SQL,Oracle 会 制定出多 种执行路 径方法,分 别计算每 个路径方法的 执行成本(估算),最后确定成本最低的执行计划 作为实际执 行计划 。一旦一 条 SQL 的执行计划 确定之后, shared pool里的游 标记录 就和这个执 行计划连 接起来。下次再有相同子游标的 SQL,则直接使用 这个执 行计划。1. 父游 标和子游 标动态 性能 视图1. v$sql, v$sqlarea, v$sql_shared_cursor 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 5 页 - - - - - - - - - 当用户发 出 sql 语句, oracle 会根据 该 sql 的文本信息 :sql text生成的 hash_value or sql_id(10g )去shared_pool中去 寻找是否有相同的sql ,如果 没有, 则为该 sql 语句生成一 个父游 标(father cursor)和一个子游 标(child cursor). 父游 标和 v$sqlarea关联 , 该视图 的每一行表示了一个父游 标, 其中的 version_count这一列表示 该父游 标含有 对应 的子游 标的个数 ,父游 标包含的信息主要是sql text 。子游 标和 v$sql 关联 ,该视图 的每一行表示了一个子游 标,子游 标包含的信息主要是该 sql 语句执行的 环境信息,如 执行计划 等. 如果要共享父子游标,实现软 解析,在父游 标可以共享,即sql 的文本完全相同的情况下,能否 实现 共享取决于子游 标,即 sql 的执行环境。 不能共享 (mismatch)的信息可以在v$sql_shared_cursor这个视图 中看到,比 较常见的情 况有: 1. optimizer_mismatch: 即优化器的模式不同,比如设置成 all_rows, first_row(n) 2. transaction_mismatch: 事务不同,如不同的用户在相同的其他 条件下 执行完全相同的sql 语句3. auth_mismatch : 授权不同 , 同上4. bind_mismatch : 绑定变量不同,很典型的情况是变量的 长度发生了 变化. SQL show parameter cursor_sharing; NAME TYPE VALUE - - - cursor_sharing string EXACT SQL select * from emp where empno=7499; SQL select * FROM emp where empno=7499; SQL select * FROM EMP WHERE empno=7499; SQL select * from emp where empno=7499; 查看父游标SQL selectsql_id, sql_text, executions, version_count from v$sqlarea where sql_text like %7499%; SQL_ID SQL_TEXT EXECUTIONS VERSION_COUNT - - - - 8unv6djhq8gug select * FROM emp where empno=7499 1 1 88gh7shrvym0q select * FROM EMP WHERE empno=7499 1 1 8rx8mmsk2ut30 select * from emp where empno=7499 2 1 1zgg3tx957f3p select sql_id, sql_text, executions, version_count from v$sqlarea where sql_te1 1查看子游标SQL select sql_id, sql_text, executions from v$sql where sql_text like %7499% order by sql_text; SQL_ID SQL_TEXT EXECUTIONS - - - 1zgg3tx957f3p select sql_id, sql_text, executions, version_count from v$sqlarea where sql_te1 88gh7shrvym0q select * FROM EMP WHERE empno=7499 1 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 5 页 - - - - - - - - - 8unv6djhq8gug select * FROM emp where empno=7499 1 8rx8mmsk2ut30 select * from emp where empno=7499 2 5qcf1hrsssh3q selectsql_id, sql_text, executions from v$sql where sql_text like %7499% 1 一个父游 标下,是可以 对应 多条子游 标记录 的。 v$sqlarea视图 中,有一列version_count表示 该父游 标有多少子游 标对应 共享 记录 。v$sql 中也有 对应标 志执行版本的列。oracle 中共享父游 标的一些前提 条件。首先是 执行的 sql 的文本必 须保持完全一致,第二个,cursor_sharing这个初始化 参数 的设置也很重要,必须为 exact ,否则 oracle 会自动的将类 似于 where id = 111 这样 的条件转换为绑 定变量的形式 . 这样,在 v$sqlarea中也无法找到这条刚刚执 行的 sql ,只能在sql 中找到 类似下列的 语句,不建议在oracle 中用参数方式绑定变量,都还是建议去程序中绑定变量为好SQL select sql_text from v$sql where sql_id = (select prev_sql_id from v$session where sid = sys_context(userenv, sid); select * from t1 where id = :SYS_B_0“这里可以看到oracle强制使用了 绑定变量. 而在 v$sqlarea中, 查找不到相 关的 sql 总结:要达到父子游标共享发生软解析的最好办法是绑定变量首先 cursor_sharing这个参数比较重要CURSOR_SHARING 定义了 SQL 共享的程度EXACT: SQL文本完全相同,并且所操作的对象也相同时共享游标SIMILAR: 文本不同,并且不因为文本不同而影响了语句的含义或者优化的维度。即如果条件列上使用了直方图,则使用硬解析。反之使用软解析。FORCE: 除非文本不同改变了语句的含义,否则强制使用游标共享。A那么我们知道在完成字面检查 后下一步的工作就是查找该语 句的父游 标是否存在,那 么首先要根据 该语 句的 内容生成 个哈希 值,这个 哈希值在 10g 中,就是通常我们看到的 SQL_ID ,然后在 库缓 存中 查找是否存 与这个 SQL_ID 相匹配的 记录 。如果存在可共享的父游 标,那 么进 入 B 阶段,如果不存在可共享的父游标,则进 入 C 阶段。B在库缓 存中 查找是否存在可共享的子游标,查找方法 应该是根据在 A 阶段得到父游 标的哈希 值在 库缓 存中 查找与 之关联 的子游 标。这里又有几 种情况:1. 如果存在且只存在一 个子游 标与 之匹配的 话,那么只接 进行执行阶段,语句不 发生硬解析; 2. 如果存在多 个子游 标,那么我揣 测优 化器 会会选择 最近 来被调用的 执行计划 ,然后 进入语句执行阶段,语句也不 发生硬解析; 3. 如果在 库缓 存中 没有找到可享的了游标,那 么进入 D 阶段。C如果在 库缓 存中 没有相匹配的父游标,就会在库缓 存中分配一些 内存,并将这个新 产生的游 标( 这个 被叫做父游 标 parent cursor )保存 进去。 与父游 标有关的关建信息是这个 SQL 语句的文本。然后进入 D 阶 段。D逻辑优 化阶 段。在 这个创 段,通 过应 用各种不同的 优化技巧,生成 语义上等同的新的 SQL 语句。做完 这件事后可 选择 的执 行计划 的数量与搜索空 间(serach space)都名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 5 页 - - - - - - - - - 会增 长。它的目的就是找出在不进 行转换时 无法被考 虑到的 执行计划 。接下 来进 入 C 阶段E物理 优化阶段。 这个阶 段会执 行好几 个操作。首先, 会生成 与每个逻辑优 化 产生的 SQL 语 句有 关的执行 计划 。接着,根据数据字典找到的统计 信息或者 动态 取样收集的统计 信息, 计算出一 个与 各 个执 行计划 相关的开销 。 最后, 拥 有最低 开销 的 执行计划 被选中。简单 的讲,查询优 化器通 过探索搜索空 间来寻 找有效的 执行计划 。接下 来进 入 D 阶段F将子游 标保存到 库缓 存阶段。首先 从库缓 存中分配一部分内 存,然后 将共享子游标 (child cursor )存 储进 去,最后 将它与 父游 标进 行 关联 。与子游 标 有关的关键内 容是执行 计划与执 行环 境。 一是保存到 库缓 存中,父游 标与 子游 标不可以分 别通过视图 v$sqlarea和 v$sql被具体化。可以通过以下3 个 字段确定一个游 标: address 、 hash_value 、和child_number。父游 标由 address和 hash_value来唯一 识别 ,而子游 标则 由这 3 个字段唯一 识别 。另外, 从 Oracle 10g开始,可以通过 使用sql_id字段 来 代替address和hash_value的 组合来达 到同 样的目的。当共享父游 标与 子游都可用,因而只需要采取A、B 两个阶 段,对应 的解析就 会被称为软 解析( soft parse) 。而 当所有的操作需要执行的 时 候, 则会 被称为 理解析( hard parse)解释 完语句的解析 过程后,我们再回 过来 看 楼主的 观点: 也就是 说在执行 sql 的时 候, oracle 会使用 绑定变量的 值,也就是 说在 进行字面 检查时 ,将绑 定变量转化为其实际值 。按照 楼主这样 解释的来理解的 话,就是 绑 定变量窥视 是发生在 语法、 语义 及访问权 限检查阶 段。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 5 页,共 5 页 - - - - - - - - -