视图 v$sql,v$sqlarea,$sqltext,v$sqltext_with_newlines 的差异
http://blog.csdn.net/leshami/article/details/8658205
视图v$sql,v$sqlarea,v$sqltext,v$sqltext_with_newlines 是几个经常容易混淆的视图,主要是提供library cache中当前缓存的sql语句的信息。这几个视图都可以提供当前有关sql语句的具体信息,但稍有差异。本文主要描述其差异并给出实例。
一、sql语句与游标
sql语句,这个没什么好说的,就是按照sql标准书写的sql语句
游标,包含shared cursor,session cursor,简单点来理解,一条sql语句对应一个或多个游标,且一条sql语句至少解析为一个游标。
当任一sql语句被解析到shared_pool中之后,必定会产生相应的游标,有下列三种情形,
a、存在可完全共享的父游标
b、父游标存在,但是由于执行环境的变化,不得不生存新的子游标
c、没有父游标存在,需要生成全新的游标
对于情形a,由于存在可共享的父游标,也就是说v$sql中必定已经存在一个对应的sql游标,我们可以查询到,执行之后对应executions及相关列会发生变化。
对于情形b或c,sql语句产生的游标会被添加到v$sql视图,也即是新增游标(b为新增子游标,c为新增父游标)。
注:在shared_pool由于aged out原则后的sql可能无法在该视图查询到,这个是另外一个话题。
二、视图差异
1、v$sql视图
假定用户A与用户B都基于自身schema创建了表t
用户A发布查询select * from t,此时共享池中产生一条与该语句的相关的sql游标,在v$sql视图体现(假定为首次执行)
不久用户B也发出select * from t的查询,同上,v$sql中也对应有一条该语句的游标
为了便于理解,我们将v$sql视图中的sql文本称之为游标,将v$sqlarea中的sql文本称为sql语句
2、v$sqlarea
对于上述情形
此时v$sqlarea则是对视图v$sql的一个聚合,也即是相当于对视图v$sql使用了distinct关键字。
尽管v$sql中出现了两条select * from t,而v$sqlarea仅为一条
v$sqlarea提供的是每条sql语句执行的汇总信息
3、v$sqltext
该视图包括Shared pool中SQL语句的完整文本,但一条SQL语句是被分成多个块来进行保存的。
对于比较短的sql语句,一个piece就搞定,对于比较长的sql语句则需要多个piece的结合来完整展现一条真正的sql语句。
4、v$sqltext_with_newlines
该视图用于完整保存SQL语句所有字符,保留SQL语句的回车和制表符。
三、示例说明
- 1、创建演示环境
- SQL> select * from v$version where rownum<2;
- BANNER
- --------------------------------------------------------------------------------
- Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
- SQL> create table t ( x varchar2(30) primary key, y int );
- SQL> exec dbms_stats.set_table_stats('SCOTT','T', numrows => 1000000, numblks=>100000);
- SQL> alter system flush shared_pool;
- SQL> select sql_text from v$sql where upper(sql_text) like 'SELECT % T LOOK_FOR_ME%'
- 2 and upper(sql_text) not like '%FROM V$SQL%';
- no rows selected
- 2、产生sql游标
- SQL> declare
- 2 l_x_number number;
- 3 l_x_string varchar2(30);
- 4 begin
- 5 execute immediate 'alter session set optimizer_mode=all_rows';
- 6 for x in (select * from t look_for_me where x = l_x_number) loop null; end loop;
- 7 for x in (select * from t look_for_me where x = l_x_string) loop null; end loop;
- 8 execute immediate 'alter session set optimizer_mode=first_rows';
- 9 for x in (select * from t look_for_me where x = l_x_number) loop null; end loop;
- 10 for x in (select * from t look_for_me where x = l_x_string) loop null; end loop;
- 11 end;
- 12 /
- PL/SQL procedure successfully completed.
- 3、分析
- SQL> col sql_text format a55
- SQL> set linesize 180
- SQL> col plan_table_output format a80 truncate
- SQL> col sql_id new_val sql_id
- SQL> select sql_id, sql_text from v$sql where upper(sql_text) like 'SELECT % T LOOK_FOR_ME %B1_';
- SQL_ID SQL_TEXT
- ------------- -------------------------------------------------------
- 1qqtru155tyz8 SELECT * FROM T LOOK_FOR_ME WHERE X = :B1
- 1qqtru155tyz8 SELECT * FROM T LOOK_FOR_ME WHERE X = :B1
- 1qqtru155tyz8 SELECT * FROM T LOOK_FOR_ME WHERE X = :B1
- 1qqtru155tyz8 SELECT * FROM T LOOK_FOR_ME WHERE X = :B1
- --从上面的查询可知,对于上面的SQL语句我们得到了相同的SQL_ID。这是因为SQL_ID是由SQL文本hash得到的一个值
- --只要SQL文本相同(完全相同),则SQL_ID一定是相同的。
- --我们从v$sql视图里边查询得到了四条相同sql_id的sql语句,也即是四个不同的游标
- --为什么同样的sql文本产生了四个不同的游标呢?这是因为:
- -- cursor 1) 使用ALL_ROWS 优化器模式, 绑定变量为number类型
- -- cursor 2) 使用ALL_ROWS 优化器模式, 绑定变量为varchar2类型
- -- cursor 3) 使用FIRST_ROWS 优化器模式, 绑定变量为number类型
- -- cursor 4) 使用FIRST_ROWS 优化器模式,绑定变量为varchar2类型
- --查询v$sql视图
- SQL> select sql_id,loaded_versions,executions,optimizer_mode, plan_hash_value,child_number,child_address
- 2 from v$sql where sql_id = '&sql_id';
- old 2: from v$sql where sql_id = '&sql_id'
- new 2: from v$sql where sql_id = '1qqtru155tyz8'
- SQL_ID LOADED_VERSIONS EXECUTIONS OPTIMIZER_ PLAN_HASH_VALUE CHILD_NUMBER CHILD_ADDRESS
- ------------- --------------- ---------- ---------- --------------- ------------ ----------------
- 1qqtru155tyz8 1 1 ALL_ROWS 1601196873 0 0000000081111008
- 1qqtru155tyz8 1 1 ALL_ROWS 2572036781 1 00000000841B1DD8
- 1qqtru155tyz8 1 1 FIRST_ROWS 1601196873 2 00000000813D1A70
- 1qqtru155tyz8 1 1 FIRST_ROWS 2572036781 3 000000007FFE3370
- --从上面的查询结果知,optimizer_mode不同,plan_hash_value的值不同,child_address的值也不同
- --尤其是child_address表明是pin到shared_pool中不同的位置
- --查看v$sqlarea视图
- SQL> select sql_id,sql_text,version_count vs_cnt,loaded_versions ld_vs,executions ex_cnt
- 2 from v$sqlarea where sql_id = '&sql_id';
- old 2: from v$sqlarea where sql_id = '&sql_id'
- new 2: from v$sqlarea where sql_id = '1qqtru155tyz8'
- SQL_ID SQL_TEXT VS_CNT LD_VS EX_CNT
- ------------- ------------------------------------------- ---------- ---------- ----------
- 1qqtru155tyz8 SELECT * FROM T LOOK_FOR_ME WHERE X = :B1 4 4 4
- --从上面的视图可知,是sql_id的一个聚合,列出了version_count以及executions的总次数等
- --下面来看看每个sql对应的执行计划
- --child_number为0的游标,此时为父游标
- SQL> select * from table(dbms_xplan.display_cursor('&sql_id',0));
- old 1: select * from table(dbms_xplan.display_cursor('&sql_id',0))
- new 1: select * from table(dbms_xplan.display_cursor('1qqtru155tyz8',0))
- PLAN_TABLE_OUTPUT
- --------------------------------------------------------------------------------
- SQL_ID 1qqtru155tyz8, child number 0
- -------------------------------------
- SELECT * FROM T LOOK_FOR_ME WHERE X = :B1
- Plan hash value: 1601196873
- --------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- --------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | | | 28616 (100)| |
- |* 1 | TABLE ACCESS FULL| T | 10000 | 292K| 28616 (6)| 00:05:44 |
- --------------------------------------------------------------------------------
- PLAN_TABLE_OUTPUT
- --------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - filter(TO_NUMBER("X")=:B1) -->存在谓词转换
- --下面是child_number为1的子游标
- SQL> select * from table(dbms_xplan.display_cursor('&sql_id',1));
- old 1: select * from table(dbms_xplan.display_cursor('&sql_id',1))
- new 1: select * from table(dbms_xplan.display_cursor('1qqtru155tyz8',1))
- PLAN_TABLE_OUTPUT
- --------------------------------------------------------------------------------
- SQL_ID 1qqtru155tyz8, child number 1
- -------------------------------------
- SELECT * FROM T LOOK_FOR_ME WHERE X = :B1
- Plan hash value: 2572036781
- --------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)
- --------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | | | 2 (100)
- | 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 30 | 2 (0)
- |* 2 | INDEX UNIQUE SCAN | SYS_C0011143 | 1 | | 1 (0)
- --------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 2 - access("X"=:B1)
- --从上面的两个执行计划中可以看出,因为绑定变量的类型不同,导致了sql语句产生了不同的执行计划
- --且第一个执行计划中使用了隐式转换
- --下面是child_number为2的子游标的执行计划
- --Author : Robinson
- --Blog : http://blog.csdn.net/robinson_0612
- SQL> select * from table(dbms_xplan.display_cursor('&sql_id',2));
- old 1: select * from table(dbms_xplan.display_cursor('&sql_id',2))
- new 1: select * from table(dbms_xplan.display_cursor('1qqtru155tyz8',2))
- PLAN_TABLE_OUTPUT
- --------------------------------------------------------------------------------
- SQL_ID 1qqtru155tyz8, child number 2
- -------------------------------------
- SELECT * FROM T LOOK_FOR_ME WHERE X = :B1
- Plan hash value: 1601196873
- --------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- --------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | | | 28616 (100)| |
- |* 1 | TABLE ACCESS FULL| T | 10000 | 292K| 28616 (6)| 00:05:44 |
- --------------------------------------------------------------------------------
- PLAN_TABLE_OUTPUT
- --------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - filter(TO_NUMBER("X")=:B1)
- --下面是child_number为3的子游标的执行计划
- SQL> select * from table(dbms_xplan.display_cursor('&sql_id',3));
- old 1: select * from table(dbms_xplan.display_cursor('&sql_id',3))
- new 1: select * from table(dbms_xplan.display_cursor('1qqtru155tyz8',3))
- PLAN_TABLE_OUTPUT
- --------------------------------------------------------------------------------
- SQL_ID 1qqtru155tyz8, child number 3
- -------------------------------------
- SELECT * FROM T LOOK_FOR_ME WHERE X = :B1
- Plan hash value: 2572036781
- --------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)
- --------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | | | 2 (100)
- | 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 30 | 2 (0)
- |* 2 | INDEX UNIQUE SCAN | SYS_C0011143 | 1 | | 1 (0)
- --------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 2 - access("X"=:B1)
- --子游标2与子游标3也是使用了不同的执行计划,这个原因与父游标0,子游标1的原因相同
- --子游标2与父游标0有相同的执行计划,从Plan hash value的值可知
- --同样,子游标3与父游标1也有相同的执行计划,从Plan hash value的值可知
- --产生不同执行计划的原因
- --v$sql_shared_cursor视图记录了那些不能共享子游标的记录并给给出原因,如下查询
- SQL> SELECT child_number,bind_mismatch, optimizer_mode_mismatch
- 2 from v$sql_shared_cursor
- 3 where sql_id = '&SQL_ID';
- old 3: where sql_id = '&SQL_ID'
- new 3: where sql_id = '1qqtru155tyz8'
- CHILD_NUMBER B O
- ------------ - -
- 0 N N
- 1 Y N
- 2 N Y
- 3 Y Y
- --从上面的查询结果可知,游标1与父游标0是由于绑定变量不匹配而导致了不可共享子游标
- --游标2则是由于不同的执行环境,游标3则是不同的执行环境与不匹配的绑定变量导致不可共享子游标
- --从上面的测试可以,父游标相同,子游标不同,执行计划可能相同,也可能不相同
- --下面的这个查询也说明了这个问题,得到的是不同的PLAN_HASH_VALUE
- SQL> select a.snap_id, a.sql_id, a.plan_hash_value,to_char(b.begin_interval_time,'yyyy-mm-dd hh24:mi:ss')
- 2 from dba_hist_sqlstat a, dba_hist_snapshot b
- 3 where a.snap_id = b.snap_id
- 4 and sql_id ='&sql_id';
- old 4: and sql_id ='&sql_id'
- new 4: and sql_id ='1qqtru155tyz8'
- SNAP_ID SQL_ID PLAN_HASH_VALUE TO_CHAR(B.BEGIN_INT
- ---------- ------------- --------------- -------------------
- 275 1qqtru155tyz8 1601196873 2013-03-08 12:00:25
- 275 1qqtru155tyz8 2572036781 2013-03-08 12:00:25
四、小结
a、本文讨论了v$sql,v$sqlarea,v$sqltext以及v$sqltext_with_newlines几个视图的差异
b、需要记住的是v$sql存储所有游标,v$sqlarea等同于使用了distinct关键字,仅保留sql语句。v$sqltext提供完整的sql语句
c、硬解析通常是由于不可共享的父游标造成的,如经常变动的SQL语句,或动态SQL或未使用绑定变量等
d、与父游标SQL文本完全一致的情形下,多个相同的SQL语句可以共享一个父游标
e、SQL文本、执行环境完全一致的情形下,子游标能够被共享,否则如果执行环境不一致则生成新的子游标
f、父游标相同,子游标不同,执行计划可能相同,也可能不相同
五、相关参考
父游标、子游标及共享游标
绑定变量及其优缺点
Oracle 硬解析与软解析
Oracle 绑定变量窥探
Oracle自适应共享游标
Whats the difference between the v$sql* views
六、更多参考:
有关Oracle RAC请参考
使用crs_setperm修改RAC资源的所有者及权限 使用crs_profile管理RAC资源配置文件 RAC 数据库的启动与关闭 再说 Oracle RAC services Services in Oracle Database 10g Migrate datbase from single instance to Oracle RAC Oracle RAC 连接到指定实例 Oracle RAC 负载均衡测试(结合服务器端与客户端) Oracle RAC 服务器端连接负载均衡(Load Balance) Oracle RAC 客户端连接负载均衡(Load Balance) ORACLE RAC 下非缺省端口监听配置(listener.ora tnsnames.ora)
ORACLE RAC 监听配置 (listener.ora tnsnames.ora) 配置 RAC 负载均衡与故障转移 CRS-1006 , CRS-0215 故障一例
基于Linux (RHEL 5.5) 安装Oracle 10g RAC
使用 runcluvfy 校验Oracle RAC安装环境
有关Oracle 网络配置相关基础以及概念性的问题请参考:
配置非默认端口的动态服务注册
配置sqlnet.ora限制IP访问Oracle Oracle 监听器日志配置与管理
设置 Oracle 监听器密码(LISTENER) 配置ORACLE 客户端连接到数据库
有关基于用户管理的备份和备份恢复的概念请参考
Oracle 冷备份 Oracle 热备份 Oracle 备份恢复概念 Oracle 实例恢复 Oracle 基于用户管理恢复的处理 SYSTEM 表空间管理及备份恢复 SYSAUX表空间管理及恢复 Oracle 基于备份控制文件的恢复(unsing backup controlfile)
有关RMAN的备份恢复与管理请参考
RMAN 概述及其体系结构 RMAN 配置、监控与管理 RMAN 备份详解 RMAN 还原与恢复 RMAN catalog 的创建和使用 基于catalog 创建RMAN存储脚本 基于catalog 的RMAN 备份与恢复 RMAN 备份路径困惑 使用RMAN实现异机备份恢复(WIN平台) 使用RMAN迁移文件系统数据库到ASM linux 下RMAN备份shell脚本 使用RMAN迁移数据库到异机
有关ORACLE体系结构请参考
Oracle 表空间与数据文件 Oracle 密码文件 Oracle 参数文件 Oracle 联机重做日志文件(ONLINE LOG FILE) Oracle 控制文件(CONTROLFILE) Oracle 归档日志 Oracle 回滚(ROLLBACK)和撤销(UNDO) Oracle 数据库实例启动关闭过程 Oracle 10g SGA 的自动化管理 Oracle 实例和Oracle数据库(Oracle体系结构)
视图 v$sql,v$sqlarea,$sqltext,v$sqltext_with_newlines 的差异的更多相关文章
- [转]数据库物化视图刷新SQL命令和查询被delete掉的数据
原文地址:http://blog.csdn.net/wangyong191212/article/details/8024161 刷新物化视图的SQL命令: 在sql语句的命令窗口并输入如下命令: e ...
- Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器
---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表. ---查询语句创建表 create table emp a ...
- 删除所有约束、表、视图等SQL脚本
--删除所有约束.表.视图等SQL脚本 --############################################### --删除所有外键约束 --################# ...
- MySQL 笔记整理(18) --为什么这些SQL语句逻辑相同,性能却差异巨大?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 18) --为什么这些SQL语句逻辑相同,性能却差异巨大? 本篇我们以三 ...
- 转:oracle常见重要视图-v$sql,v$sql_plan,v$sqltext,v$sqlarea,v$sql_plan_statistcs
v$sql V$SQL中存储具体的SQL语句. 一条语句可以映射多个cursor,因为对象所指的cursor可以有不同用户(如例1).如果有多个cursor(子游标)存在,在V$SQLAREA为所有c ...
- SQL Server(六)——索引、视图和SQL编程
1.索引 添加索引,设计界面,在任何一列前右键--索引/键--点击进入添加某一列为索引 2.视图 视图就是我们查询出来的虚拟表 创建视图:create view 视图名 as SQL查询语句,分组,排 ...
- SQLserver视图修改sql
语法: alter view dbo.视图名 as 更新后的视图SQL go 举个栗子: 原视图名为YOUR_VIEW其中SQL为: select * form TableA 更新视图: alter ...
- Spark2 Dataset之视图与SQL
// 创建视图 data.createOrReplaceTempView("Affairs") val df1 = spark.sql("SELECT * FROM Af ...
- 06 数据库入门学习-视图、sql注入、事务、存储过程
一.视图 1.什么是视图 视图本质是一张虚拟的表 2.为什么要用 为了原表的安全 只要有两大功能 1.隐藏部分数据,开放指定数据 2.视图可以将查询结果保存,减少sql语句的次数 特点: 1.视图使用 ...
随机推荐
- 贪心 UVALive 6832 Bit String Reordering
题目传送门 /* 贪心:按照0或1开头,若不符合,选择后面最近的进行交换.然后选取最少的交换次数 */ #include <cstdio> #include <algorithm&g ...
- Linux单机环境下HDFS伪分布式集群安装操作步骤v1.0
公司平台的分布式文件系统基于Hadoop HDFS技术构建,为开发人员学习及后续项目中Hadoop HDFS相关操作提供技术参考特编写此文档.本文档描述了Linux单机环境下Hadoop HDFS伪分 ...
- 'NSUnknownKeyException' … setValue:forUndefinedKey:]: …not key value coding compliant
解决一个问题: 当我添加一个IBout, 报了如下错误 NSUnknownKeyException' … setValue:forUndefinedKey:]: …not key value codi ...
- qt5.5版本的creator构建套件自动检测为警告
原创,转载请注明http://www.cnblogs.com/dachen408/p/7226188.html 原因,安装qt在E盘,winsdksetup也在E盘 的原因,卸载winsdksetup ...
- windows ubuntu bcdeditor
双系统. 先装windows,后装ubuntu12.04 为了避免grub引导,所以安装bcdeditor. 平时使用没有什么不适,可是每次linux升级内核以后,grub列表可能就会消失,自然是不能 ...
- Bash Template
#/bin/bash #set -x set -e usage() { cat <<EOF Usage: `basename $` [OPTIONS] <non-option arg ...
- php+nginx 限制上传文件大小
问题:在后台上传8M大小的图片,上传不成功 nginx返回413,如下图所示: 分析:nginx配置文件或者php中,可上传的大小设置太小了 解决办法------检查nginx和php的配置文件里面的 ...
- CAD使用SetxDataLong写数据(com接口)
主要用到函数说明: MxDrawEntity::SetxDataLong 写一个long扩展数据,详细说明如下: 参数 说明 [in] BSTR val 字符串值 szAppName 扩展数据名称 n ...
- element-UI el-table添加序号列时序号永远都是从1开始?
Part.1 示例 当我们想在 el-table 中添加序号列时,如下: <el-table-column label="序号" type="index" ...
- Less简介及安装
CSS的短板 作为前端学习者的我们 或多或少都要学些 CSS ,它作为前端开发的三大基石之一,时刻引领着 Web 的发展潮向. 而 CSS 作为一门标记性语言,可能 给初学者第一印象 就是简单易懂,毫 ...