本文主要讲解“ACS和PL/SQL的分析”,感兴趣的朋友不妨看一下。本文介绍的方法简单、快速、实用。让边肖带你学习《ACS与PL/SQL分析》!
ACS与PL/SQL
我们来看看ACS在PL/SQL中的工作,结果可能会让你非常失望。
首先,构建一个PL/SQL,它使用我们在本章中创建的表T:
SQLvarsql_idvarchar2(255)
sqlaltersystemflush shared _ pool;
系统改变了。
SQLdeclare
2xinteger
3nnumber
4开始
5foriin1.10圈
6ifi=1then
7x:=500000
8else
9x :=1;
10endif
11selectcount(object_id)进入intonfromtwhereidx
12endloop
13end
14/
PL/sqlprocedureccessfullycompleted。
该PL/SQL将首先执行一次“选择计数(对象标识)到nfromtwhereid 100000”,然后执行九次“选择计数(对象标识)到nfromtwhereid 1”。执行完了,看看会不会用ACS。
SQLselect
2sql_id
3,子_号
4、处决
5、parse_calls
6,buffer _ gets
7,is_bind_sensitive
8,is_bind_aware
> 9 from
10 v$sql
11 where
12 sql_id =' gp03v5aw085v3';
SQL_ID CHILD_NUMBER EXECUTIONS PARSE_CALLS BUFFER_GETS IS IS
--------------- ------------ ---------- ----------- ----------- -- --
gp03v5aw085v3 0 10 1 646875 Y N
非常可惜,这个SQL并没有产生多个子游标,虽然已经识别到这个SQL为绑定敏感is_bind_sensitive='Y',但是is_bind_aware='N'。
SQL> SELECT hash_value, sql_id, child_number, bucket_id, COUNT 2 FROM v$sql_cs_histogram 3 WHERE sql_id='gp03v5aw085v3' 4 ORDER BY sql_id, child_number; HASH_VALUE SQL_ID CHILD_NUMBER BUCKET_ID COUNT ---------- --------------- ------------ ---------- ---------- 3087275875 gp03v5aw085v3 0 0 1 3087275875 gp03v5aw085v3 0 2 9 3087275875 gp03v5aw085v3 0 1 0 |
虽然v$sql_cs_histogram已经监控到了处理行数的巨大改变,但是却没有生成新的游标。
SQL>select * from table(dbms_xplan.display_cursor(:sql_id,null,'+PEEKED_BINDS')); PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------- SQL_ID gp03v5aw085v3, child number 0 ------------------------------------- SELECT COUNT(OBJECT_ID) FROM T WHERE ID > :B1 Plan hash value: 3694077449 ------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 4 (100)| | | 1 | SORT AGGREGATE | | 1 | 10 | | | | 2 | TABLE ACCESS BY INDEX ROWID| T | 1 | 10 | 4 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | I | 1 | | 3 (0)| 00:00:01 | ------------------------------------------------------------------------------------- Peeked Binds (identified by position): -------------------------------------- 1 - :B1 (NUMBER): 5000000 Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("ID">:B1) |
执行计划一直沿用的是第一次产生的执行计划,根据Peeked Binds (identified by position):的值为5000000可以推断出来。我们尝试在SQL里增加bind_aware hint看看,这个hint的作用在本章的最佳实践小节中介绍,这里不再赘述。
SQL>declare 2 x integer; 3 n number; 4 begin 5 for i in 1..10 loop 6 if i = 1 then 7 x := 5000000; 8 else 9 x := 1; 10 end if; 11 select /*+ bind_aware */count(object_id) into n from t where id > x; 12 end loop; 13 end; 14 / PL/SQL procedure successfully completed. SQL>select 2 sql_id 3 , child_number 4 , executions 5 , parse_calls 6 , buffer_gets 7 , is_bind_sensitive 8 , is_bind_aware 9 from 10 v$sql 11 where 12 sql_id = '5542a2rzny69v'; SQL_ID CHILD_NUMBER EXECUTIONS PARSE_CALLS BUFFER_GETS IS IS --------------- ------------ ---------- ----------- ----------- -- -- 5542a2rzny69v 0 10 1 687396 Y Y |
虽然优化器已经标记这个游标is_bind_aware='Y'了,但是依然没有新的游标产生出来。在MOS上查找类似的问题,会发现一个BUG:
Bug 8357294 : ADAPTIVE cursor SHARING DOESN'T WORK FOR STATIC SQL cursorS FROM PL/SQL
标题的意思是由于BUG,ACS不能工作在PL/SQL的静态游标里。但是根据测试动态游标也不能工作。
SQL>declare 2 x integer; 3 n number; 4 begin 5 for i in 1..10 loop 6 if i = 1 then 7 x := 5000000; 8 else 9 x := 1; 10 end if; 11 execute immediate 12 'select count(object_id) from t where id > :x' into n using x; 13 end loop; 14 end; 15 / PL/SQL procedure successfully completed. SQL>select 2 sql_id 3 , child_number 4 , executions 5 , parse_calls 6 , buffer_gets 7 , is_bind_sensitive 8 , is_bind_aware 9 from 10 v$sql 11 where 12 sql_id = '6qwg6gauwbpm8'; SQL_ID CHILD_NUMBER EXECUTIONS PARSE_CALLS BUFFER_GETS IS IS --------------- ------------ ---------- ----------- ----------- -- -- 6qwg6gauwbpm8 0 10 1 687580 Y N |
文中提到了Session_Cached_Cursors在设置为0后,ACS就可以正常工作了,经过试验也如它所说。
SQL>alter session set Session_Cached_Cursors=0; Session altered. SQL>alter system flush shared_pool; System altered. SQL>declare 2 x integer; 3 n number; 4 begin 5 for i in 1..10 loop 6 if i = 1 then 7 x := 5000000; 8 else 9 x := 1; 10 end if; 11 select count(object_id) into n from t where id > x; 12 end loop; 13 end; 14 / PL/SQL procedure successfully completed. SQL>select 2 sql_id 3 , child_number 4 , executions 5 , parse_calls 6 , buffer_gets 7 , is_bind_sensitive 8 , is_bind_aware 9 from 10 v$sql 11 where 12 sql_id = ' gp03v5aw085v3'; SQL_ID CHILD_NUMBER EXECUTIONS PARSE_CALLS BUFFER_GETS IS IS --------------- ------------ ---------- ----------- ----------- -- -- gp03v5aw085v3 0 2 3 76405 Y N gp03v5aw085v3 1 8 7 517480 Y Y SQL>select * from table(dbms_xplan.display_cursor('gp03v5aw085v3',null)); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------- SQL_ID gp03v5aw085v3, child number 0 ------------------------------------- SELECT COUNT(OBJECT_ID) FROM T WHERE ID > :B1 Plan hash value: 3694077449 ------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 4 (100)| | | 1 | SORT AGGREGATE | | 1 | 10 | | | | 2 | TABLE ACCESS BY INDEX ROWID| T | 1 | 10 | 4 (0)| 00:00:01 | |* 3 | INDEX RANGE SCAN | I | 1 | | 3 (0)| 00:00:01 | ------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("ID">:B1) SQL_ID gp03v5aw085v3, child number 1 ------------------------------------- SELECT COUNT(OBJECT_ID) FROM T WHERE ID > :B1 Plan hash value: 2966233522 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 14373 (100)| | | 1 | SORT AGGREGATE | | 1 | 10 | | | |* 2 | TABLE ACCESS FULL| T | 4999K| 47M| 14373 (2)| 00:02:53 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("ID">:B1) |
可以看到ACS已经工作了,在v$sql_cs_histogram里也为新游标产生了新的行。
SQL> SELECT hash_value, sql_id, child_number, bucket_id, COUNT 2 FROM v$sql_cs_histogram 3 WHERE sql_id='gp03v5aw085v3' 4 ORDER BY sql_id, child_number; HASH_VALUE SQL_ID CHILD_NUMBER BUCKET_ID COUNT ---------- --------------- ------------ ---------- ---------- 3087275875 gp03v5aw085v3 0 1 0 3087275875 gp03v5aw085v3 0 0 1 3087275875 gp03v5aw085v3 0 2 1 3087275875 gp03v5aw085v3 1 1 0 3087275875 gp03v5aw085v3 1 0 0 3087275875 gp03v5aw085v3 1 2 8 |
到此,相信大家对“ACS与PL/SQL的工作情况分析”有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/93981.html