v$sql和v$sqlarea

官方文档解释: V$SQL lists statistics on shared SQL areas without the GROUP BY clause and contains one row for each child of the original SQL text entered. Statistics displayed in V$SQL are normally updated at the end of query execution. However, for long running queries, they are updated every 5 seconds. This makes it easy to see the impact of long running SQL statements while they are still in progress. V$SQLAREA displays statistics on shared SQL areas and contains one row per SQL string. It provides statistics on SQL statements that are in memory, parsed, and ready for execution.

环境准备: sql_id,executions,first_load_time,last_load_time,disk_reads,buffer_gets,hash_value,plan_hash_value from v$sql where sql_text like '%zhuo%'; select sql_text,sql_id,version_count,executions,first_load_time,last_load_time,disk_reads,buffer_gets,hash_value,plan_hash_value from v$sqlarea where sql_text like '%zhuo%';

OWNER TABLE_NAME


ZHUO ZHUO TEST ZHUO

SQL> select count(*) from zhuo.zhuo;

COUNT(*)

 18333

SQL> select count(*) from test.zhuo;

COUNT(*)

    42

两个用户下面有名字相同的一张表,但是表结构和内容都是不一样的。 为了避免查询到的数据影响,观察具体字段含义,把共享池和buffer cache清空: SQL> alter system flush shared_pool; SQL> alter system flush BUFFER_CACHE; 结果如下:

下面执行一次sql,观察哪些指标会发生变化: hash_value:其实和sql_id是一个含义,都是唯一标识一条sql,两者可以相互转换 first_load_time:第一次载入shared pool的时间 last_load_time:最后一次载入shared pool的时间,也就是最后一次执行这条sql的时间 再次清空buffer cache,观察逻辑读和物理读的变化 SQL> alter system flush BUFFER_CACHE;

System altered. SQL> set autot trace SQL> select count(*) from zhuo;

Execution Plan Plan hash value: 1214160148


| Id | Operation | Name | Rows | Cost (%CPU)| Time | | 0 | SELECT STATEMENT | | 1 | 71 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| ZHUO | 18333 | 71 (0)| 00:00:01 |

Statistics 25 recursive calls 0 db block gets 269 consistent gets 244 physical reads 0 redo size 528 bytes sent via SQLNet to client 523 bytes received via SQLNet from client 2 SQL*Net roundtrips to/from client 4 sorts (memory) 0 sorts (disk) 1 rows processed

和上面的结果一致,sql真正执行耗费的物理读和逻辑读和v$sql里面记录的数一致。 在执行一次: SQL> select count(*) from zhuo;

Execution Plan Plan hash value: 1214160148


| Id | Operation | Name | Rows | Cost (%CPU)| Time | | 0 | SELECT STATEMENT | | 1 | 71 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| ZHUO | 18333 | 71 (0)| 00:00:01 |

Statistics 0 recursive calls 0 db block gets 246 consistent gets 0 physical reads 0 redo size 528 bytes sent via SQLNet to client 523 bytes received via SQLNet from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed

从执行计划可知:所有的数据都已缓存到内存中,所以物理读为0,全部为逻辑读。再看v$sql里面记录的,应该是和上次执行完成的差值,才是一次sql执行耗费的物理读和逻辑读。 物理读:244-244=0 逻辑读:515-269=246 这就和执行计划的资源消耗相同了。

executions:执行次数,这个sql现在就执行了2次。里面记录的值也是2.

下面看v$sqlarea的区别: 用test用户执行一次查询: SQL> conn test/test; Connected.

SQL> select count(*) from zhuo;

COUNT(*) 42

查看v$sql和v$sqlarea

v$sql里面显示一条记录。v$sqlarea显示有关这个sql的两条记录。 v$sql里面的executions,一个是2次,一个是2次。v$sqlarea里面累加了,executions是3. v$sql里面记录的,test用户的disk read为4,buffer get为24. v$sqlare里面却是累加的:244+4=248,515+24=539. v$sqlarea里面的version count为2,sql版本数。 通过前文可以知道,文本相同的SQL语句,在数据库中的意义可能完全不同。比如数据库中存在两个用户zhuo和test,两个用户各拥有一张数据表zhuo。 那么当两个用户发出一个查询select count(*) from zhuo时,这个查询访问的对象,返回的结果可能完全不同,zhuo的查询访问的是zhuo.zhuo表,而DBTAN用户访问的则是test.zhuo表。但是单从SQL_TEXT上来说,这两个SQL没有任何区别 在这个视图中,Oracle将v$sql中的sql_text相同的2个子指针合并起来,执行次数等信息也都进行了累计,version_count也显示为2,这就是v$sqlarea的聚合作用。