v$sql, v$sqlarea, v$sqltext的区别
1、先说简单的--v$sqltext中有内存中完整的sql语句,SQL被piece字段分割成64字节的片断,但没有该语句的统计信息,比如执行次数等。
SQL> desc v$sqltext
Name Null? Type
----------------------------------------- -------- ----------------------------
ADDRESS RAW(8)
HASH_VALUE NUMBER
COMMAND_TYPE NUMBER
PIECE NUMBER
SQL_TEXT VARCHAR2(64)
而底层的数据源时 x$kglna,查看其定义为:
select inst_id,kglhdadr, kglnahsh, kgloboct, piece, name from x$kglna where kgloboct != 0
2、v$sql与v$sqlarea这两个视图都包含统计信息,比较容易混淆:
v$sql与v$sqlarea的源都是一个:X$KGLCURSOR
SELECT view_definition FROM v$fixed_view_definition WHERE view_name='GV$SQL';
SELECT view_definition FROM v$fixed_view_definition WHERE view_name='GV$SQLAREA';
通过VIEW_DEFINITION,可以看到
V$SQLAREA 是做了group by:
group by inst_id,kglnaobj,kglhdpar,kglnahsh,kglnatim, kglobts0, kglobt19, kglobts1, kglobt20,
decode(kglobt33, 1, 'Y', 'N'), kglhdclt having sum(decode(kglobt09,0,kglobt02,0)) != 0
而V$SQL WHERE 语句 仅仅是做了条件过滤:
from x$kglcursor where
kglhdadr != kglhdpar and kglobt02 != 0
v$sql join to v$sql_plan就代表了具体的SQL执行计划。
关联字段:
ADDRESS RAW(4)
HASH_VALUE NUMBER
CHILD_NUMBER NUMBER
在10G,可以通过 SQL_ID直接关联两张视图,比9i简化多了。
即使是相同的数据库用户,若 session 的优化模式、session 级的参数 等不一样,相同内容的SQL,其执行计划也能不同。
v$sql能记录下这些不同执行计划的SQL语句。
而v$sqlarea忽略了执行计划等差异,只是在形式上sql文本看起来一样。相当于做了个聚合,是多个不同执行计划的sql的聚合和累计信息
具体一点:v$sqlarea相当于是按INST_ID, KGLNAOBJ, KGLHDPAR, KGLNAHSH, KGLNATIM, GLOBTS0,GLOBT19, KGLOBTS1, KGLOBT20,DECODE(KGLOBT33, 1, 'Y', 'N'),KGLHDCLT这些列的自v$sql的group by,也就是说v$sql的每一行表示的是每一个sql语句的一个version,而v$sqlarea存放的是相同语句不同version一个汇总。
实际调优中建议使用v$sql,相对来说比v$sqlarea快,而且还不会产生share pool latch的争用。
下面做个测试:
环境搭建:
SQL> desc t
Name Null? Type
----------------------------------------- -------- ----------------------------
I NUMBER(38)
SQL> select * from t;
I
----------
200
100
SQL> var dd number;
SQL> begin
2 :dd := 100;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL>
SQL> select count(*) from t lookup_me where i = :dd;
COUNT(*)
----------
1
SQL> show parameter optim
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
object_cache_optimal_size integer 102400
optimizer_dynamic_sampling integer 1
optimizer_features_enable string 9.2.0
optimizer_index_caching integer 0
optimizer_index_cost_adj integer 100
optimizer_max_permutations integer 2000
optimizer_mode string CHOOSE
SQL> alter
2
SQL> alter session set optimizer_mode=first_rows;
SQL> begin
2 :dd := 200;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> select count(*) from t lookup_me where i = :dd;
COUNT(*)
----------
1
SQL> select address,hash_value, child_number , sql_text
2 from v$sql
where upper(sql_text)
like
'SELECT % T LOOKUP_ME %'; 3 4 5
ADDRESS HASH_VALUE CHILD_NUMBER
---------------- ---------- ------------
SQL_TEXT
--------------------------------------------------------------------------------
00000003E6C69250 1010443947 0
select count(*) from t lookup_me where i = :dd
00000003E6C69250 1010443947 1
select count(*) from t lookup_me where i = :dd
可以看到v$sql 里有两条记录是关于刚才的查询对象的。
SQL> select sql_text, VERSION_COUNT, USERS_OPENING, ADDRESS, HASH_VALUE
2 from v$sqlarea
where upper(sql_text)
like
'SELECT % T LOOKUP_ME %'; 3 4 5
SQL_TEXT
--------------------------------------------------------------------------------
VERSION_COUNT USERS_OPENING ADDRESS HASH_VALUE
------------- ------------- ---------------- ----------
select count(*) from t lookup_me where i = :dd
2 2.5 00000003E6C69250 1010443947
而在v$sqlarea中只有一条记录。
3、因v$sql及v$sqlarea存放着统计信息在调优时使用居多,但其sql是不全的,如果想获得完整的sql就要用v$sqltext了。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/40239/viewspace-558328/ ,如需转载,请注明出处,否则将追究法律责任。