通过案例学调优之--SQL Profile
通過案例學調(diào)優(yōu)之--SQL Profile
一、什么是SQL Profile(概要)
?? ? ? ?SQL Profile在性能優(yōu)化中占有一個重要的位置。
?????? MOS里這么描述SQL Profile:
?????? SQL Profile是10g中的新特性,作為自動SQL調(diào)整過程的一部分,由Oracle企業(yè)管理器來管理。除了OEM,SQL Profile可以通過DBMS_SQLTUNE包來進行管理。
?????? 查詢優(yōu)化器有時候會因為缺乏足夠的信息,而對一條SQL語句做出錯誤的估計,生成糟糕的執(zhí)行計劃。而自動SQL調(diào)整通過SQL概要分析來解決這個問題,自動調(diào)整優(yōu)化器會生成這條SQL語句的一個概要,稱作SQL Profile。它由針對這條語句的一些輔助統(tǒng)計信息組成,通過采樣和局部執(zhí)行技術(shù)來確認,必要的話,會調(diào)整執(zhí)行計劃中的估計值。在SQL概要分析中,自動調(diào)整優(yōu)化器還可以通過一條SQL語句的執(zhí)行歷史信息來設置合適的優(yōu)化器參數(shù),比如將OPTIMIZER_MODE參數(shù)由ALL_ROWS改為FIRST_ROWS。
?????? 換句話說,SQL概要是一個對象,它包含了可以幫助查詢優(yōu)化器為一個特定的SQL語句找到高效執(zhí)行計劃的信息。這些信息包括執(zhí)行環(huán)境、對象統(tǒng)計和對查詢優(yōu)化器所做評估的修正信息。它的最大優(yōu)點之一就是在不修改SQL語句和會話執(zhí)行環(huán)境的情況下影響查詢優(yōu)化器的決定。(《Oracle性能診斷藝術(shù)》)
?????? SQL Profile中包含的并非單個執(zhí)行計劃的信息,必須注意的是,SQL Profile不會固定一個SQL語句的執(zhí)行計劃。當表的數(shù)據(jù)增長或者索引創(chuàng)建、刪除,使用同一個SQL Profile的執(zhí)行計劃可能會改變,而儲存在SQL Profile中的信息會繼續(xù)起作用。然而,經(jīng)過一段很長的時間之后,它的信息有可能會過時,需要重新生成。
?????? SQL Profile的作用范圍由CATEGORY屬性來控制,這個屬性決定了哪些用戶會話可以應用這個概要。你可以從DBA_SQL_PROFILES中的CATEGORY字段來查看這個屬性。默認情況下,所有概要文件都創(chuàng)建為DEFAULT范疇,這意味著所有SQLTUNE_CATEGORY初始化參數(shù)為DEFAULT的用戶會話都可以使用這個概要。你可以修改這個屬性,比如將其改為SCO,則SQLTUNE_GATEGORY參數(shù)為SCO的用戶會話才能使用它,利用這個功能,你可以在一個受限制的環(huán)境中來測試一個SQL Profile。
16:42:03?SYS@?prod?>desc?dba_sql_profilesName??????????????????????????????????????????????????????????????Null?????Type-----------------------------------------------------------------?--------?--------------------------------------------NAME??????????????????????????????????????????????????????????????NOT?NULL?VARCHAR2(30)CATEGORY??????????????????????????????????????????????????????????NOT?NULL?VARCHAR2(30)SIGNATURE?????????????????????????????????????????????????????????NOT?NULL?NUMBERSQL_TEXT??????????????????????????????????????????????????????????NOT?NULL?CLOBCREATED???????????????????????????????????????????????????????????NOT?NULL?TIMESTAMP(6)LAST_MODIFIED??????????????????????????????????????????????????????????????TIMESTAMP(6)DESCRIPTION????????????????????????????????????????????????????????????????VARCHAR2(500)TYPE???????????????????????????????????????????????????????????????????????VARCHAR2(7)STATUS?????????????????????????????????????????????????????????????????????VARCHAR2(8)FORCE_MATCHING?????????????????????????????????????????????????????????????VARCHAR2(3)TASK_ID????????????????????????????????????????????????????????????????????NUMBERTASK_EXEC_NAME?????????????????????????????????????????????????????????????VARCHAR2(30)TASK_OBJ_ID????????????????????????????????????????????????????????????????NUMBERTASK_FND_ID????????????????????????????????????????????????????????????????NUMBERTASK_REC_ID????????????????????????????????????????????????????????????????NUMBER16:50:43?SYS@?prod?>select?name,?CATEGORY,sql_text,status?from?dba_sql_profiles; no?rows?selected
?????? SQL Profile可以作用在如下表達式中:SELECT; UPDATE; INSERT(在包含SELECT子句的情況下); DELETE; CREATE TABLE(包含SELECT子句的情況下); MERGE(UPDATE或INSERT操作)。
二、SQL Profile的管理
Oracle執(zhí)行SQL語句的步驟如下:
1. 用戶傳送要執(zhí)行的SQL語句給SQL引擎
2. SQL引擎要求查詢優(yōu)化器提供執(zhí)行計劃
3. 查詢優(yōu)化取得系統(tǒng)統(tǒng)計信息、SQL語句引用對象的對象統(tǒng)計信息、SQL概要和構(gòu)成執(zhí)行環(huán)境的初始化參數(shù)
4. 查詢優(yōu)化器分析SQL語句并產(chǎn)生執(zhí)行計劃
5. 將執(zhí)行計劃傳遞給SQL引擎
6. SQL引擎執(zhí)行SQL語句
?SQL Profile可以由OEM來管理,也可以通過DBMS_SQLTUNE包來手動使用。
(1)、使用OEM時步驟如下:
1. 在Performance頁面,點擊Top Activity。出現(xiàn)了Top Activity頁面
2. 在Top SQL下面,點擊正在使用SQL Profile的SQL表達式的SQL ID鏈接,會出現(xiàn)一個SQL Details頁面
3. 點擊Plan Control選項卡,在SQL Profiles and Outlines下面會顯示一個SQL profile的列表
4. 選擇你想要管理的SQL Profile,可以做如下操作:啟用或禁用、移除
5. 會出現(xiàn)一個確認的頁面,點擊Yes繼續(xù),No取消
(2)、使用DBMS_SQLTUNE包
如果使用DBMS_SQLTUNE包,你需要CREATE ANY SQL_PROFILE、DROP ANY SQL_PROFILE還有ALTER ANY SQL_PROFILE的系統(tǒng)權(quán)限。
1)、創(chuàng)建sql profile
使用DBMS_SQLTUNE.ACCEPT_SQL_PROFILE過程來接受并創(chuàng)建SQL Tuning Advisor建議的SQL Profile
DECLARE? my_sqlprofile_name?VARCHAR2(30);? BEGIN? my_sqlprofile_name?:=?DBMS_SQLTUNE.ACCEPT_SQL_PROFILE?(?? task_name?=>?'my_sql_tuning_task',? name?=>?'my_sql_profile');? END;這個過程的傳入?yún)?shù)中有一個可選參數(shù)force_match,默認為FALSE。當設置為FALSE時,不區(qū)分空白和大小寫,為TRUE時,空白、大小寫和字面量都不區(qū)分。通過企業(yè)管理器來接受SQL概要時,這個參數(shù)在ORACLE11g中才可以設置。
2)、修改SQL Profile
可以修改STATUS、NAME、DESCRIPTION和CATEGORY屬性
BEGIN? DBMS_SQLTUNE.ALTER_SQL_PROFILE(? name?=>?'my_sql_profile',?? attribute_name?=>?'STATUS',?? value?=>?'DISABLED');? END;? /3)、刪除SQL Profile
begin? DBMS_SQLTUNE.DROP_SQL_PROFILE(name?=>?'my_sql_profile');? end;? /對我們來說,重點在于創(chuàng)建SQL Profile時的my_sql_tuning_task上,它通過函數(shù)create_tuning_task來創(chuàng)建,執(zhí)行這個函數(shù)需要傳遞下面的參數(shù)之一:SQL語句文本、存儲在共享池中的SQL語句引用(sql_id)、存儲在自動工作量資料庫中的SQL語句引用(sql_id)、SQL調(diào)優(yōu)集名稱。
?什么是SQL調(diào)優(yōu)集(tuning set)?簡單來講,SQL調(diào)優(yōu)集是存儲一系列SQL語句及其相關信息的對象集合,這些信息包括執(zhí)行環(huán)境、運行統(tǒng)計和可選的執(zhí)行計劃。
下面引用MOS提供的一個示例來演示一下這個過程
案例分析:
1、scott用戶執(zhí)行sql 17:19:56?SCOTT@?prod?>create?table?test?(n?number); Table?created.17:20:16?SCOTT@?prod?>begin 17:20:24???2??for?i?in?1..100000?loop 17:20:36???3??insert?into?test?values?(i); 17:20:47???4??commit; 17:20:49???5??end?loop; 17:20:52???6??end; 17:20:53???7??/ PL/SQL?procedure?successfully?completed.17:22:02?SCOTT@?prod?>create?index?test_ind?on?test(n); Index?created.17:22:55?SCOTT@?prod?>exec?dbms_stats.gather_table_stats(user,'TEST'?,cascade=>true); PL/SQL?procedure?successfully?completed.17:23:15?SCOTT@?prod?>set?autotrace?on 17:23:43?SCOTT@?prod?>select?*?from?test?where?n=100;N ----------100 Elapsed:?00:00:00.01 Execution?Plan ---------------------------------------------------------- Plan?hash?value:?3357096749 ----------------------------------------------------------------------------- |?Id??|?Operation????????|?Name?????|?Rows??|?Bytes?|?Cost?(%CPU)|?Time?????| ----------------------------------------------------------------------------- |???0?|?SELECT?STATEMENT?|??????????|?????1?|?????5?|?????1???(0)|?00:00:01?| |*??1?|??INDEX?RANGE?SCAN|?TEST_IND?|?????1?|?????5?|?????1???(0)|?00:00:01?| ----------------------------------------------------------------------------- Predicate?Information?(identified?by?operation?id): ---------------------------------------------------1?-?access("N"=100) Statistics ----------------------------------------------------------1??recursive?calls0??db?block?gets3??consistent?gets0??physical?reads0??redo?size415??bytes?sent?via?SQL*Net?to?client419??bytes?received?via?SQL*Net?from?client2??SQL*Net?roundtrips?to/from?client0??sorts?(memory)0??sorts?(disk)1??rows?processed對此sql建立sql?profile: 17:24:02?SCOTT@?prod?>select?/*+?no_index(test,test_ind)?*/?*?from?test?where?n=100;N ----------100 Elapsed:?00:00:00.01 Execution?Plan ---------------------------------------------------------- Plan?hash?value:?1357081020 -------------------------------------------------------------------------- |?Id??|?Operation?????????|?Name?|?Rows??|?Bytes?|?Cost?(%CPU)|?Time?????| -------------------------------------------------------------------------- |???0?|?SELECT?STATEMENT??|??????|?????1?|?????5?|????69???(2)|?00:00:01?| |*??1?|??TABLE?ACCESS?FULL|?TEST?|?????1?|?????5?|????69???(2)|?00:00:01?| -------------------------------------------------------------------------- Predicate?Information?(identified?by?operation?id): ---------------------------------------------------1?-?filter("N"=100) Statistics ----------------------------------------------------------1??recursive?calls0??db?block?gets191??consistent?gets0??physical?reads0??redo?size415??bytes?sent?via?SQL*Net?to?client419??bytes?received?via?SQL*Net?from?client2??SQL*Net?roundtrips?to/from?client0??sorts?(memory)0??sorts?(disk)1??rows?processed2、通過sys用戶建立sql?profile(使用dbms_sqltune包) 17:28:26?SYS@?prod?>declare 17:29:34???2 17:29:34???3????my_task_name?VARCHAR2(30); 17:29:34???4 17:29:34???5????my_sqltext?CLOB; 17:29:34???6 17:29:34???7????begin 17:29:34???8 17:29:34???9???????my_sqltext?:=?'select?/*+?no_index(test?test_ind)?*/?*?from?test?where?n=100'; 17:29:34??10 17:29:34??11???????my_task_name?:=?DBMS_SQLTUNE.CREATE_TUNING_TASK( 17:29:34??12 17:29:34??13???????sql_text?=>?my_sqltext, 17:29:34??14 17:29:34??15???????user_name?=>?'SCOTT', 17:29:34??16 17:29:34??17???????scope?=>?'COMPREHENSIVE', 17:29:34??18 17:29:34??19???????time_limit?=>?60, 17:29:34??20 17:29:34??21???????task_name?=>?'my_tun1', 17:29:34??22 17:29:34??23???????description?=>?'Task?to?tune?a?query?on?a?specified?table'); 17:29:34??24 17:29:34??25??end; 17:29:35??26??/ PL/SQL?procedure?successfully?completed.建立調(diào)優(yōu)任務: 17:29:37?SYS@?prod?>begin 17:30:39???2 17:30:39???3??DBMS_SQLTUNE.EXECUTE_TUNING_TASK(?task_name?=>?'my_tun1'); 17:30:39???4 17:30:39???5??end; 17:30:39???6 17:30:39???7??/ PL/SQL?procedure?successfully?completed.查看調(diào)優(yōu)task: 17:32:47?SYS@?prod?>set?long?1000 17:33:17?SYS@?prod?>set?longchunksize?1000 17:33:24?SYS@?prod?>set?linesize?100 17:33:32?SYS@?prod?>SELECT?DBMS_SQLTUNE.REPORT_TUNING_TASK('my_tun1')?from?dual DBMS_SQLTUNE.REPORT_TUNING_TASK('MY_TUN1') ---------------------------------------------------------------------------------------------------- GENERAL?INFORMATION?SECTION ------------------------------------------------------------------------------- Tuning?Task?Name???:?my_tun1 Tuning?Task?Owner??:?SYS Workload?Type??????:?Single?SQL?Statement Scope??????????????:?COMPREHENSIVE Time?Limit(seconds):?60 Completion?Status??:?COMPLETED Started?at?????????:?11/07/2014?17:30:41 Completed?at???????:?11/07/2014?17:30:49 ------------------------------------------------------------------------------- Schema?Name:?SCOTT SQL?ID?????:?b1wdr0b0qzsbg SQL?Text???:?select?/*+?no_index(test?test_ind)?*/?*?from?test?where?n=100 ------------------------------------------------------------------------------- DBMS_SQLTUNE.REPORT_TUNING_TASK('MY_TUN1') ---------------------------------------------------------------------------------------------------- FINDINGS?SECTION?(1?finding) ------------------------------------------------------------------------------- 1-?SQL?Profile?Finding?(see?explain?plans?section?below) --------------------------------------------------------A?potentially?better?execution?plan?was?found?for?this?statement.Recommendation?(estimated?benefit:?99.41%)17:34:58?SYS@?prod?>execute?dbms_sqltune.accept_sql_profile(task_name?=>'my_tun1',task_owner?=>?'SYS',?replace?=>?TRUE); PL/SQL?procedure?successfully?completed.建立sql?profile: 17:39:22?SYS@?prod?>DECLARE 17:41:13???2 17:41:13???3??my_sqlprofile_name?VARCHAR2(30); 17:41:13???4 17:41:13???5??begin 17:41:13???6 17:41:13???7??my_sqlprofile_name?:=?DBMS_SQLTUNE.ACCEPT_SQL_PROFILE?( 17:41:13???8 17:41:13???9??task_name?=>?'my_tun1', 17:41:13??10 17:41:13??11??name?=>?'my_sqlprofile',force_match=>false); 17:41:13??12 17:41:13??13??end; 17:41:15??14??/ DECLARE * ERROR?at?line?1: ORA-13830:?SQL?profile?with?category?DEFAULT?already?exists?for?this?SQL?statement ORA-06512:?at?"SYS.DBMS_SQLTUNE_INTERNAL",?line?16259 ORA-06512:?at?"SYS.PRVT_SQLPROF_INFRA",?line?31 ORA-06512:?at?"SYS.DBMS_SQLTUNE",?line?7133 ORA-06512:?at?line?717:44:28?SYS@?prod?>DECLARE 17:46:00???2 17:46:00???3??my_sqlprofile_name?VARCHAR2(30); 17:46:00???4 17:46:00???5??begin 17:46:00???6 17:46:00???7??my_sqlprofile_name?:=?DBMS_SQLTUNE.ACCEPT_SQL_PROFILE?( 17:46:00???8 17:46:00???9??task_name?=>?'my_tun1', 17:46:00??10 17:46:00??11??name?=>?'my_sqlprofile',force_match=>false,CATEGORY=>'scott'); 17:46:00??12 17:46:00??13??end; 17:46:01??14??/ PL/SQL?procedure?successfully?completed.17:53:49?SYS@?prod?>select?name,?CATEGORY,sql_text,status?from?dba_sql_profiles; NAME???????????????????????????CATEGORY ------------------------------?------------------------------ SQL_TEXT ---------------------------------------------------------------------------------------------------- STATUS -------- SYS_SQLPROF_0149899c759a0000???DEFAULT select?/*+?no_index(test?test_ind)?*/?*?from?test?where?n=100 ENABLED my_sqlprofile??????????????????SCOTT select?/*+?no_index(test?test_ind)?*/?*?from?test?where?n=100 ENABLED刪除存在的sql?profile: 17:53:51?SYS@?prod?>exec?DBMS_SQLTUNE.DROP_SQL_PROFILE(name?=>'SYS_SQLPROF_0149899c759a0000'); PL/SQL?procedure?successfully?completed.17:55:20?SYS@?prod?>exec?DBMS_SQLTUNE.DROP_SQL_PROFILE(name?=>'my_sqlprofile'); PL/SQL?procedure?successfully?completed.重新建立sql?profile: 17:55:35?SYS@?prod?>DECLARE 17:56:13???2 17:56:13???3??my_sqlprofile_name?VARCHAR2(30); 17:56:13???4 17:56:13???5??begin 17:56:13???6 17:56:13???7??my_sqlprofile_name?:=?DBMS_SQLTUNE.ACCEPT_SQL_PROFILE?( 17:56:13???8 17:56:13???9??task_name?=>?'my_tun1', 17:56:13??10 17:56:13??11??name?=>?'my_sqlprofile'); 17:56:13??12 17:56:13??13??end; 17:56:16??14??/ PL/SQL?procedure?successfully?completed. Elapsed:?00:00:00.04查看sql?profile: 18:01:48?SYS@?prod?>col?name?for?a20 18:01:55?SYS@?prod?>r1*?select?name,CATEGORY,SQL_TEXT,TASK_EXEC_NAME?,STATUS?from?dba_sql_profiles NAME?????????????????CATEGORY???SQL_TEXT --------------------?----------?-------------------------------------------------- TASK_EXEC_NAME?????????????????STATUS ------------------------------?-------- my_sqlprofile????????DEFAULT????select?/*+?no_index(test?test_ind)?*/?*?from?testwhere?n=100 EXEC_427???????????????????????ENABLED3、以scott用戶的身份進行驗證 18:01:55?SYS@?prod?>conn?scott/tiger Connected. 18:02:43?SCOTT@?prod?>set?autotrace?on 18:02:46?SCOTT@?prod?>?select?/*+?no_index(test?test_ind)?*/?*?from?test?where?n=100;N ----------100 Elapsed:?00:00:00.05 Execution?Plan ---------------------------------------------------------- Plan?hash?value:?3357096749 ----------------------------------------------------------------------------- |?Id??|?Operation????????|?Name?????|?Rows??|?Bytes?|?Cost?(%CPU)|?Time?????| ----------------------------------------------------------------------------- |???0?|?SELECT?STATEMENT?|??????????|?????1?|?????5?|?????1???(0)|?00:00:01?| |*??1?|??INDEX?RANGE?SCAN|?TEST_IND?|?????1?|?????5?|?????1???(0)|?00:00:01?| ----------------------------------------------------------------------------- Predicate?Information?(identified?by?operation?id): ---------------------------------------------------1?-?access("N"=100) Note ------?SQL?profile?"my_sqlprofile"?used?for?this?statement Statistics ----------------------------------------------------------790??recursive?calls0??db?block?gets168??consistent?gets6??physical?reads116??redo?size415??bytes?sent?via?SQL*Net?to?client419??bytes?received?via?SQL*Net?from?client2??SQL*Net?roundtrips?to/from?client13??sorts?(memory)0??sorts?(disk)1??rows?processed
可以看出即使使用了‘no_index'的hint,sql執(zhí)行計劃仍使用index 訪問。? 使用了 ?SQL profile "my_sql_profile" used for this statement ?
由這個例子我們可以發(fā)現(xiàn),在必要情況下,SQL Profile可以讓hint失效!
轉(zhuǎn)載于:https://blog.51cto.com/tiany/1574132
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的通过案例学调优之--SQL Profile的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (转)那些年我们一起清除过的浮动
- 下一篇: Android组件之BroadCast简