`
tooby
  • 浏览: 110273 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Oracle 视图 v$sql,v$sqlarea,$sqltext,v$sqltext_with_newlines 的差异

    博客分类:
  • SQL
 
阅读更多

视图 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体系结构)

分享到:
评论

相关推荐

    Oracle v$sqlarea, v$sql, v$sqltext视图说明

    简单描述Oracle v$sqlarea, v$sql, v$sqltext视图说明

    学些动态性能表-word版

    学习动态性能表(四)--v$sqltext&v$sqlarea 学习动态性能表(五)--v$session 学习动态性能表(六)--v$session_wait&v$session_event 学习动态性能表(七)--v$process 学习动态性能表(八)--v$lock&v$locked_object ...

    查詢高消耗CPU的pid的SQL

    FROM v$sqltext a WHERE (a.hash_value, a.address) IN ( SELECT DECODE (sql_hash_value, 0, prev_hash_value, sql_hash_value ), DECODE (sql_hash_value, 0, prev_sql_addr, sql_address) FROM v$session b WHERE...

    获取top前10个Oracle的进程(支持多实例)

    FROM V$SQLTEXT_WITH_NEWLINES WHERE ADDRESS = HEXTORAW('000000007C9641F0') AND HASH_VALUE = 2890562617 ORDER BY PIECE /* concatenate */ Update goods a Set (goodsid,obligatestr1,goodsflag,fgoodsid,...

    oracle 查看当前会话执行的sql语句

    查询ORACLE 系统中当前会话正在执行的有关SQL语句。

    oracle 12c SYSAUX表空间过大

    DB到12.2.0.1版本之后,由于统计信息顾问导致SYSAUX 过快增长

    深入解析Oracle.DBA入门进阶与诊断案例

    6.2.10 V$SQL与V$SQLAREA视图 287 6.2.11 Oracle 10g中version_count过高的诊断 292 6.2.12 诊断案例二:临时表引发的竞争 297 6.2.13 小结 299 第7章 重做(Redo) 300 7.1 Redo的作用 300 7.2 Redo的...

    ORACLE精品脚本笔记

    监控当前数据库谁在运行什么SQL语句 &lt;br&gt;SELECT osuser, username, sql_text from v$session a, v$sqltext b where a.sql_address =b.address order by address, piece; &lt;br&gt;13. 监控字典缓冲区 ...

    Query-Test-Framework:一组用于在 Oracle 数据库上运行查询、捕获指标和绘制结果图表的工具

    查询-测试-框架一组用于在 Oracle 数据库上运行查询... 几乎与 query-capture.sql 相同,只是第 5 个参数是并行度sql-list.sql从 gv$sql_monitor 和 gv$ sqltext列出最近的 SQL,允许您使用 sql_id 调用 sql-capture.sq

    SQLText1.zip

    能把SQL语句查询的来的结构,转换成EXCEL格式

    sql 存储过程分页

    CREATE PROC myx_prPageRecordset @queryStr nvarchar(1000), @keyField nvarchar (200), @pageSize int, @pageNumber int AS BEGIN DECLARE @sqlText AS nvarchar(4000) DECLARE @sqlTable AS ...

    sybase sql执行慢,如何调优

    dbcc sqltext(spid) –spid 进程号 2、执行下述代码,查看当前进程执行计划(索引引用情况) sp_showplan spid –spid 进程号 3、若不在进程队列中,执行下述代码,查看当前sql段的执行计划(索引引用情况) SET ...

    C#访问SqlServer设置链接超时的方法

    本文实例讲述了C#访问SqlServer设置链接超时的方法。分享给大家供大家参考。具体实现方法如下: 下面这段代码设置超时时间为60秒,默认为30秒 using (connection) { SqlCommand sqlcommand = connection....

    进销存v3源码20121106

    SQL SERVER执行的SQL语句在此文件夹下面(CangDiHuo\CangDiHuo\Content\SQLText),分开了2000,2005,2008三个版本的 注意: 开发环境为Visual Studio 2010,数据库为SQL Server 2008,数据库文件在 DB文件夹中附加就行...

    C#查询SqlServer数据库并返回单个值的方法

    static public string GetSqlAsString(string sqlText, SqlParameter[] sqlParameters, string databaseConnectionString) { string result = ""; SqlDataReader reader; SqlConnection connection = new ...

    mysql开启慢查询(EXPLAIN SQL语句使用介绍)

    主要介绍了mysql开启慢查询 EXPLAIN SQL语句,需要的朋友可以参考下

    数据库课程设计---删除

    删除学号: private void btnDelete_... bool tag = ExecuteSQL(sqlText); if (!tag) { MessageBox.Show("删除失败!"); return; } LoadStudent(); SetControlsEnable(true); ClearContent(); } } }

    留言板管理

    if(this.TextBox1.Text.ToString()!="") { string sqlText=... DAL.ExecuteSql exec =new.ExecuteSql(); int flag =exec.run(sqlText) if(flag==1) { this.DropDownList2.SelectedValue="不可以";好

    delphi 版本的自动升级程序

    SQLTEXT.MDB为数据库更新用的文件,请自行修改记录,但是记录先后顺序一定要根据指令的先后顺序来添加。 mentoro.htm为存放在网站上的文件,具体内容自已改吧。(您也可以用INI文件) CHIS.INI为更新配置文件(其他...

Global site tag (gtag.js) - Google Analytics