使用sql profile實現outline的功能
[@more@]
使用sql profile實現outline的功能
上一篇 / 下一篇 2010-09-23 10:53:56 / 個人分類:oracle管理
首先看一個查詢:
sys@EBANK>selectobject_name from t where object_id between 1000 and 2000;
1001 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 15384 | 345K| 533 (1)| 00:00:07 |
|* 1 | TABLE ACCESS FULL| T | 15384 | 345K| 533 (1)| 00:00:07 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_ID"<=2000 AND "OBJECT_ID">=1000)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2387 consistent gets
0 physical reads
29996 redo size
27644 bytes sent via SQL*Net to client
1107 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1001 rows processed
對於這個查詢,由於表中統計資訊過舊,錯誤的選擇了全表掃描,加索引提示:
sys@EBANK>sys@EBANK>select/*+ index(t idx_t) */ object_name from t where object_id between 1000 and 2000;
1001 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1594971208
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 15384 | 345K| 15421 (1)| 00:03:06 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 15384 | 345K| 15421 (1)| 00:03:06 |
|* 2 | INDEX RANGE SCAN | IDX_T | 15384 | | 35 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID">=1000 AND "OBJECT_ID"<=2000)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
203 consistent gets
0 physical reads
0 redo size
27644 bytes sent via SQL*Net to client
1107 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1001 rows processed
對於上述查詢,顯然加索引提示是合理的,而當無法修改應用時,我們需要從資料庫端來干預此sql的執行計劃,採用sql profile可以完成此功能
我們暫且把未加提示的sql稱之為sql_nohi,加了提示的sql稱之為sql_hi,執行如下儲存過程,該儲存過程的功能首先取得加sql_hi的outline資料,也就是一系列hints,
然後使用這些outline資料來對sql_nohi生成profile,也就是說讓sql_nohi來使用sql_hi的執行計劃:
declare
ar_hint_table sys.dbms_debug_vc2coll;
ar_profile_hints sys.sqlprof_attr := sys.sqlprof_attr();
cl_sql_text clob;
i pls_integer;
begin
with a as (
select
rownum as r_no
, a.*
from
table(
-- replace with
-- DBMS_XPLAN.DISPLAY_AWR
-- if required
dbms_xplan.display_cursor(
'&&good_sql_id'
, null
, 'OUTLINE'
)
-- dbms_xplan.display_awr(
-- '&&1'
-- , null
-- , null
-- , 'OUTLINE'
-- )
) a
),
b as (
select
min(r_no) as start_r_no
from
a
where
a.plan_table_output = 'Outline Data'
),
c as (
select
min(r_no) as end_r_no
from
a
, b
where
a.r_no > b.start_r_no
and a.plan_table_output = ' */'
),
d as (
select
instr(a.plan_table_output, 'BEGIN_OUTLINE_DATA') as start_col
from
a
, b
where
r_no = b.start_r_no + 4
)
select
substr(a.plan_table_output, d.start_col) as outline_hints
bulk collect
into
ar_hint_table
from
a
, b
, c
, d
where
a.r_no >= b.start_r_no + 4
and a.r_no <= c.end_r_no - 1
order by
a.r_no;
select
sql_text
into
cl_sql_text
from
-- replace with dba_hist_sqltext
-- if required for AWR based
-- execution
v$sql
-- sys.dba_hist_sqltext
where
sql_id = '&&bad_sql_id';
-- this is only required
-- to concatenate hints
-- splitted across several lines
-- and could be done in SQL, too
i := ar_hint_table.first;
while i is not null
loop
if ar_hint_table.exists(i + 1) then
if substr(ar_hint_table(i + 1), 1, 1) = ' ' then
ar_hint_table(i) := ar_hint_table(i) || trim(ar_hint_table(i + 1));
ar_hint_table.delete(i + 1);
end if;
end if;
i := ar_hint_table.next(i);
end loop;
i := ar_hint_table.first;
while i is not null
loop
ar_profile_hints.extend;
ar_profile_hints(ar_profile_hints.count) := ar_hint_table(i);
i := ar_hint_table.next(i);
end loop;
dbms_sqltune.import_sql_profile(
sql_text => cl_sql_text
, profile => ar_profile_hints
, name => 'PROFILE_&&1'
-- use force_match => true
-- to use CURSOR_SHARING=SIMILAR
-- behaviour, i.e. match even with
-- differing literals
, force_match => false
);
end;
/
此過程可以完成上述功能,測試如下:
首先取得兩條sql的sql_id:
sys@EBANK>selectsql_id,sql_text from v$sql where sql_text like ('select%from t where object_id between 1000 and 2000%');
SQL_ID SQL_TEXT
------------- ------------------------------------------------------------
dmn81fk77n9z6 select object_name from t where object_id between 1000 and 2
000
036w3z13k3wgh select /*+ index(t idx_t) */ object_name from t where object
_id between 1000 and 2000
執行gen_sql_profile.sql:
sys@EBANK>@gen_sql_profile.sql
Enter value for good_sql_id: 036w3z13k3wgh
old 17: '&&good_sql_id'
new 17: '036w3z13k3wgh'
Enter value for bad_sql_id: dmn81fk77n9z6
old 83: sql_id = '&&bad_sql_id';
new 83: sql_id = 'dmn81fk77n9z6';
Enter value for profile_name: test
old 112: , name => 'PROFILE_&profile_name'
new 112: , name => 'PROFILE_test'
PL/SQL procedure successfully completed.
此時再執行未加hints的sql:
sys@EBANK>setautot traceonlysys@EBANK>selectobject_name from t where object_id between 1000 and 2000;
1001 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1594971208
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 15384 | 345K| 15421 (1)| 00:03:06 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 15384 | 345K| 15421 (1)| 00:03:06 |
|* 2 | INDEX RANGE SCAN | IDX_T | 15384 | | 35 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID">=1000 AND "OBJECT_ID"<=2000)
Note
-----
- SQL profile "PROFILE_test" used for this statement
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
203 consistent gets
0 physical reads
0 redo size
27644 bytes sent via SQL*Net to client
1106 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1001 rows processed
可以看到,oracle使用了sql profile,sql的執行計劃得以改變,對於上述sql profile,是sql_id相同的條件下生效的,改變一下where條件中的值:
sys@EBANK>execdbms_sqltune.drop_sql_profile('PROFILE_test');
PL/SQL procedure successfully completed.
sys@EBANK>@gen_sql_profile
Enter value for good_sql_id: 036w3z13k3wgh
old 17: '&&good_sql_id'
new 17: '036w3z13k3wgh'
Enter value for bad_sql_id: dmn81fk77n9z6
old 83: sql_id = '&&bad_sql_id';
new 83: sql_id = 'dmn81fk77n9z6';
Enter value for profile_name: TEST
old 112: , name => 'PROFILE_&profile_name'
new 112: , name => 'PROFILE_TEST'
PL/SQL procedure successfully completed.
sys@EBANK>setautot traceonly explainsys@EBANK>selectobject_name from t where object_id between 1000 and 2001;
Execution Plan
----------------------------------------------------------
Plan hash value: 1594971208
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 15399 | 345K| 15436 (1)| 00:03:06 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 15399 | 345K| 15436 (1)| 00:03:06 |
|* 2 | INDEX RANGE SCAN | IDX_T | 15399 | | 35 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID">=1000 AND "OBJECT_ID"<=2001)
Note
-----
- SQL profile "PROFILE_TEST" used for this statement
sys@EBANK>selectobject_name from t where object_id between 1000 and 3000;
Execution Plan
----------------------------------------------------------
Plan hash value: 1594971208
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 30736 | 690K| 30809 (1)| 00:06:10 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 30736 | 690K| 30809 (1)| 00:06:10 |
|* 2 | INDEX RANGE SCAN | IDX_T | 30736 | | 69 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID">=1000 AND "OBJECT_ID"<=3000)
Note
-----
-SQL profile "PROFILE_TEST" used for this statement
可見,對於這種沒有使用繫結變數的sql,即使是where條件中的取值不同,仍然能夠使用sql profile,這是由於設定了force_match => true的原因。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/642366/viewspace-1060245/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- sql profile的使用2011-11-10SQL
- sql profile使用2013-02-13SQL
- ORACLE SQL PROFILE使用2017-04-21OracleSQL
- sql_profile的使用(一)2015-09-11SQL
- zt_sql baseline_sql profile_sql outline修改固定執行計劃2013-07-29SQL
- SQL Server profile使用技巧2017-01-19SQLServer
- 檢視SQL PROFILE使用的HINT2013-09-29SQL
- SQL Profile 實驗032016-04-05SQL
- SQL Profile 實驗022016-04-05SQL
- SQL Profile 實驗012016-04-02SQL
- SQL Azure使用Excel實現BI功能:PowerPivotTW2022-03-21SQLExcel
- [Shell] AWK實現SQL的功能(1)2016-09-14SQL
- [SQL Server]分頁功能的實現2009-08-03SQLServer
- 用pandas實現SQL功能2021-03-08SQL
- 使用SQL Profile進行SQL優化案例2014-08-08SQL優化
- 【SQL Profile】coe_xfr_sql_profile.sql內容2017-06-28SQL
- sql profile2010-09-20SQL
- MySQL Profile檢視SQL的資源使用2014-04-29MySql
- 【OUTLINE】使用Oracle Outline技術暫時鎖定SQL的執行計劃2012-07-02OracleSQL
- 使用SQL Profile進行SQL最佳化案例2014-11-27SQL
- 使用sql profile固定執行計劃2016-05-18SQL
- SQL Server--實現 Limit m, n 的功能2017-09-06SQLServerMIT
- sql最佳化:使用sql profile最佳化sql語句2015-09-02SQL
- 使用SQL PROFILE 給出合理的執行計劃2015-08-25SQL
- SQL PROFILE 測試2014-07-24SQL
- 修改profile實現資源限制2012-05-12
- 使用product_user_profile來實現使用者許可權的設定2010-11-06
- 使用Webcam實現拍照功能2017-02-07Web
- 如何用SQL語句實現以下功能.2008-05-16SQL
- Oracle profile的使用2011-05-23Oracle
- sql tuning task和sql profile2014-01-28SQL
- maven 使用maven profile實現多環境可移植構建2015-09-29Maven
- 如何在SQL Server中實現 Limit m,n 的功能2021-09-09SQLServerMIT
- 巧用SQL Server(Ranking)實現view的排序功能2011-08-15SQLServerView排序
- 使用 jQuery 實現分頁功能2019-09-11jQuery
- 使用redis實現互粉功能2019-02-16Redis
- 使用VB實現OLE拖放功能2004-11-19
- SQL語句 實現自動編號功能2010-04-07SQL