Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1149043
  • 博文数量: 231
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 2662
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-03 16:35
个人简介

学无止境

文章分类

全部博文(231)

文章存档

2014年(7)

2013年(103)

2011年(11)

2010年(53)

2009年(57)

分类: Oracle

2013-12-04 14:52:36

创建一张表,其中status字段数据存在倾斜,该字段上存在索引
SQL> create index idx_tab3_status on tab3(status);
SQL> select status,count(*) from tab3 group by status;

STATUS            COUNT(*)
--------------- ----------
20                     608
10                  143328

对表进行分析
exec dbms_stats.gather_table_stats(ownname => 'ldy',tabname => 'tab3',cascade => true,method_opt => 'for columns size auto status');


采用常量值进行查询,可以看到当status='20'时,走了索引,当status='10'时,走全表扫描。对于SQL存在倾斜的条件字段,如果需要从不同的取值中得到收益(执行计划不同),最好不使用绑定变量,而采用常量带入。绑定变量是优化的方法,而不是优化的目的。

SQL> select * from tab3 where status='20';

608 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1608671757

-----------------------------------------------------------------------------------------------
| Id  | Operation                   | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                 |   608 | 32832 |     6   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TAB3            |   608 | 32832 |     6   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IDX_TAB3_STATUS |   608 |       |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("STATUS"='20')

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          9  recursive calls
          0  db block gets
        178  consistent gets
          3  physical reads
          0  redo size
      19209  bytes sent via SQL*Net to client
        932  bytes received via SQL*Net from client
         42  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
        608  rows processed

SQL> select * from tab3 where status='10';

143328 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 2826512543

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |   110K|  5816K|   125   (3)| 00:00:02 |
|*  1 |  TABLE ACCESS FULL| TAB3 |   110K|  5816K|   125   (3)| 00:00:02 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("STATUS"='10')

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          7  recursive calls
          0  db block gets
      10199  consistent gets
          5  physical reads
          0  redo size
    5163384  bytes sent via SQL*Net to client
     105597  bytes received via SQL*Net from client
       9557  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
     143328  rows processed


使用绑定变量,首次执行先绑定变量a='10',再次执行绑定变量a='20',对比执行计划
var a varchar2(20);
exec :a:='10';
select * from tab3 where status=:a;

exec :a:='20';
select * from tab3 where status=:a;


SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------
SQL_ID  4j5q5hwnszu05, child number 0
-------------------------------------
select * from tab3 where status=:a

Plan hash value: 2826512543

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |       |       |   125 (100)|          |
|*  1 |  TABLE ACCESS FULL| TAB3 |   110K|  5816K|   125   (3)| 00:00:02 |

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1 / TAB3@SEL$1

Outline Data
-------------

  /*+

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('10.2.0.4')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "TAB3"@"SEL$1")
      END_OUTLINE_DATA
  */

Peeked Binds (identified by position):
--------------------------------------

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------

   1 - :A (VARCHAR2(30), CSID=871): '10'  <-- 窥视的变量值

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("STATUS"=:A)

Column Projection Information (identified by operation id):
-----------------------------------------------------------


PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
   1 - "TAB3"."ID"[NUMBER,22], "TAB3"."NAME"[VARCHAR2,60],
       "STATUS"[VARCHAR2,15]

Note
-----
   - dynamic sampling used for this statement
  
  
将绑定变量变为'20',peeked binds的值并没有变化

SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
SQL_ID  4j5q5hwnszu05, child number 0
-------------------------------------
select * from tab3 where status=:a

Plan hash value: 2826512543

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |       |       |   125 (100)|          |
|*  1 |  TABLE ACCESS FULL| TAB3 |   110K|  5816K|   125   (3)| 00:00:02 |

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

   1 - SEL$1 / TAB3@SEL$1

Outline Data
-------------

  /*+

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('10.2.0.4')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "TAB3"@"SEL$1")
      END_OUTLINE_DATA
  */

Peeked Binds (identified by position):
--------------------------------------

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------

   1 - :A (VARCHAR2(30), CSID=871): '10'   <-- 仍然是第一次窥视的变量值

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("STATUS"=:A)

Column Projection Information (identified by operation id):
-----------------------------------------------------------


PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
   1 - "TAB3"."ID"[NUMBER,22], "TAB3"."NAME"[VARCHAR2,60],
       "STATUS"[VARCHAR2,15]

Note
-----
   - dynamic sampling used for this statement
  
  

查看目前共享池里游标的执行计划,发现为走了全表扫描

SQL> select * from table(dbms_xplan.display_cursor('4j5q5hwnszu05'));

SQL_ID  4j5q5hwnszu05, child number 0
-------------------------------------
select * from tab3 where status=:a
 
Plan hash value: 2826512543
 
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |       |       |   125 (100)|          |
|*  1 |  TABLE ACCESS FULL| TAB3 |   110K|  5816K|   125   (3)| 00:00:02 |
--------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("STATUS"=:A)
 
Note
-----
   - dynamic sampling used for this statement
 

 

这之后,带入变量为'20',无论执行多少次,执行计划都没有变化,数据库只在硬解析时,窥视了变量值,并生成执行计划,之后的软解析不再窥视(该问题发生在11g之前,11g有了ACS的新特性,每次绑定变量都会被窥视)

如果想要重新生成执行计划,通常想到的是刷新共享池,但是在繁忙系统,并行共享池较大的数据库中,风险较大。
可以采取一些操作重新使得这一条SQL语句硬解析。


1.采用表授权的方式
revoke select on ldy.tab1 from system;
grant  select on ldy.tab1 to system;

2.将统计信息导出再导入
exec dbms_stats.create_stat_table(ownname => 'ldy',stattab => 'ldy_tab_stat');
exec dbms_stats.export_table_stats(ownname =>'LDY' ,tabname => 'TAB3',stattab => 'ldy_tab_stat');
exec dbms_stats.import_table_stats(ownname => 'LDY',tabname =>'TAB3' ,stattab => 'ldy_tab_stat');

3.在10.2.0.4及以上版本,可以通过dbms_shared_pool来清除指定的游标
alter session set events '5614566 trace name context forever';

select hash_value, address, sql_id
from v$sql
where sql_id = '4j5q5hwnszu05';

HASH_VALUE ADDRESS          SQL_ID
---------- ---------------- -------------
 697296901 00000000711487C0 4j5q5hwnszu05
 
exec dbms_shared_pool.purge ('00000000711487C0,697296901','C');

阅读(4125) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

wittzhang2015-06-08 16:37:29

感谢分享