201704171025
01、

列rows記錄的就是執行計划中每一個執行步驟所對應的Cardinality的值
列Cost(%CPU)記錄的就是執行計划中的每一個執行步驟對應的成本
02、
Computed Cardinality=Original Cardinality * Selectivity
03、簡單謂詞連接


04、B樹索引

05、索引連接方式
索引唯一掃描
是針對唯一索引的掃描,它僅僅適用於where條件里是 等值查詢的目標sql。因為掃描的對象時唯一性索引,索引索引唯一性掃描的結果之多返回一條記錄
索引范圍掃描
適用於所有類型的B樹索引。
當掃描對象時唯一性索引時,此時目標sql的where條件一定是范圍查詢(謂詞條件為 between 、<、>);
當掃描對象是非唯一性索引時,此時目標sql的where條件沒有限制(可以是等值,也可以是范圍查詢)
索引全掃描
適用於所有類型的B樹索引。
要掃描目標索引所有葉子快的所有索引行。索引全掃描需要掃描目標索引的所有葉子快。
oracle在做索引全掃描時只需要訪問必要的分支塊等位到魚尾該索引最左邊的葉子快的第一行索引行,就可以利用該索引椰子塊之間的雙向指針鏈表,從左至右一次掃描葉子塊的所有索引行
索引快速全掃描
只適合於CBO
可以單塊讀可以多快讀
結果集不一定是有序的。因為FFS 時 oracle根據索引行在磁盤上的 物理存儲位置 掃描,而不是根據索引行的邏輯順序掃描。因此結果不一定有序
索引跳躍式掃描
僅僅適用於那些目標索引前導列的distinct值數量較少、后續非前導列的可選擇性有非常好的情形。因為索引跳躍式掃描的執行效率一定會隨着目標索引前導列的distinct值數量的遞增而遞減
06、
hint 強制使用9i版本
/*+optimizer_feature_enable(9.2.0) */
201704172148
--嵌套循環連接的優缺點和應用場景
從上述嵌態循環連接的具體執行過程可以看出:如果驅動表所對應的驅動結果集的記錄數較少,同時
在被驅動表的連接列上又存在唯一性索引(或者在被驅動表的連接列上存在選擇性很好的非唯一索引),那么此時使用嵌套循環連接的執行效率就會非常高;但如果驅動表所對應的驅動結果集的記錄很多,即便在被驅動表的連接列上存在索引,此時使用嵌套循環連接的執行效率也不會高。
只要驅動結果集的記錄數較少,那就具備了做嵌套循環連接的前提條件,而驅動結果集是在對驅動表應用了目標sql指定的謂詞條件)所得到的結果集,所以大表也可以作為嵌套循環連接的驅動表。關鍵看目標SQL中指定的謂詞條件(如果有的話)能否將結果集降下來。
嵌套循環連接有其他方式所沒有的一個優點:嵌套循環連接可以實現快速響應
1021
本質上SQL ID和SQL HASH VALUE是一回事,它們是可以互相轉換的,這也是方法
BMS_XPLAN.DISPLAY CURSOR所傳入的第一個參數的值可以是SQL ID,也可以是SQL HASH VALUE
SQL> select lower(trim(13yfu3wh150aqt!))sql id, trunc(mod (sum((instr(10123456789abedfghikmnpqrstuvwxyz' niintgsett)),level,1))-1)*power(32,1ength(trin( 3yfuswhis0asth nnntsubstr(lower(trim('3yfu3whis0aqt')),level,1))-1)'pove nint-level)),power(2,32)))hash value
from dual
1045
執行 select * from table(dbms_xplan.display_awr('sql_id')) ,用於查看指定sql的歷史執行計划
1103 oradebug
oradebug setmypid
oradebug event 10046 trace name context forever,1evel 12;
select statements
oradebug tracefile_name
oradebug event 10046 trace name context off
tkprof ......trc
cr :consistent reads
pr :physical reads
1411

先從最開頭一致持續往右看,直到看到最右邊的並列的地方;
對於不並列的,靠右的先執行;
如果見到並列的,就從上往下看。對於並列的部分,靠上的先執行
TABLE ACCESS FULL
BUFFER SORT
Plan hash value:2105702960
------------------------------------------------------------------------------------------------------------------
|Id | Operation | Name | Rowa | Bytes | Cost(%CPU) | Time |
| 0 | SELBCT STATEMENT | | | | 3082(100))| |
| 1 | SORT AGGREGATE | | 1 | 54 | | |
| 2 | CONCATENATION | | | | | |
| 3 | MERGE JOIN CARTESIAN | | 470K | 24M | 1969(4) | 00:00:24 |
| 4 | TABLE ACCESS PULL |OWBATN | 1 | 34 | 851(5) | 00:00:11 |
| 5 | BUFFER SORT | | 316K| 6175K| 1118(3) | 00:00:14 |
| 6 | TABLE ACCB88 FULL |UPLTER | 316K| 6175K| 1118(3) | 00:00:14 |
| 7 | FILTER | | | | | |
| 8 | HASH JOIN | | 37522| 1978K| 1109(6) | 00:00:14 |
| 9 | TABLE ACCESS PULL |OWBATN | 20956| 695K| 852(5) | 00:00:11 |
| 10 | INDEX FAST FULL SCAN |IDX_UPLTER_UTETKT | 316K| 6175K| 246(6) | 00:00:03 |
| 11 | SORT AGGRBGATE | | 1 | 38 | | |
| 12 | TABLE ACCES8 BY INDEX ROWID | UPLTER | 1 | 30 | 4(0) | 00:00:01 |
| 13 | INDEX RANGE scAN | IDx_UPLTER_UTETKT | 2 | | 3(0) | 00:00:01 |
·13
eedieate Information (identitied by operetton ttii
otp,on "O"."OATE8m"="F"OR "o","oATPgn"-'I”))
XPLAN包查看執行計划的執行順序
列的屬性為 null,那么該字段可能會存 null類型的數據。因此 如果按照 訪問索引的方式訪問 可能會漏掉數據。 索引上不會有null數據
dbms_xplan.display_cursor(null,null,'advanced') 弊端多多啊,必須在執行完sql之后 馬上執行這個操作。才可以看到執行計划 太被動
比如 表t的索引列為a,然后我執行查詢:select a,b from t where a = 'xxx';
這樣的話,靠a上的索引提供不了查詢所要的數據a+b,所以要去表中找,這個過程叫做回表?
0903
whenever sqlerror exit sql.sqlcode;
dbms_sqltune.import_sql_profile
索引聚簇因子
更新聚簇因子 exec dbms_stats.set_index_stats(ownname=>'user_name',indname=>'index_name',clstfct=>24000000,no_invalidate=>false)
查詢聚簇因子 select idx1.index_name,idx1.clustering_factor from dba_indexes idx1
1045
cursor
oracle數據庫中的shared cursor 又可細分為 parent cursor 和child cursor 這兩種類型。通過查詢視圖 v$sqlarea 可查看 parent cursor,v$sql 可查看child cursor
Parent Cursor 和 Child Cursor的結構是一樣的(它們都是以庫緩存對象句柄的方式緩存在庫級存中,
Namespace屬性的值均為CRSR),它們的區別在於目標SQL的SOL文本會存儲在其Parent Curser所對應的緩存對象句柄的屬性Name中(Child Cursor對應的庫緩存對象句柄的Name屬性值為空,這意味着只有通過
Parent Cursor才能找到相應的Child Cursor),而該SQL的解析樹和執行計划則會存儲在其Child Cursor所對應的庫緩存對象句柄的Heap6中,同時Oracle會在該SQL所對應的Parent Cursor的Heap 0的的Child table中,
存儲從屬於該Parent Cursor的所有Child Cursor的庫緩存對象句柄地址(這意味着Oracle可以通過訪問 Paren cursor
中的Child table而依次順序訪問從屬於該Parent Cursor的所有Child Cursor)。
parent cursor 會存儲該sql的sql文本,child cursor 會存儲 該sql對應的解析數和執行計划
1415 errorstack
alter session set events'immediate trace name errorstack level 3'
隱式游標
sql%FOUND true/false
sql%NOTFOUND true/false sql語句被執行成功后受影響的行數是否是0
sql%isopen 隱式游標是否處於open狀態 恆為 false
sql%rowcount 一條sql語句成功執行后受影響而改變的記錄的數量
1524
參考游標的定義方式以下四種
第一種方式:
type typ_cur_emp is ref cursor return emp%rowtype;
cur_emp typ_cur_emp;
第二種方式:
type typ_result is record(ename emp,ename%type,sal emp.salstype;
type typ_cur strong is ref cursor return typ_result;
cur emp typ cur_stong;
第三種方式:
tvpe typ_cur weak is ref cursor;
cur_emp typ_cur_weak;
第四種方式:
cur emp SYS_REFCURSOR;
上述范例HL/SQL代碼用四種不同的方式分別定義了同一個參考游標ctr.emm
1559
PL/SQL中select語句的綁定變量典型用法
execute immediate 'select ename from emp where empno=:1' using 7369;
1608
PL/SQL代碼中批量fetch對應的語法:
fetch cursor_name bluk collect into [自定義的數組] <limit 數字[建議值通常 1000]>
forall i in 1..[自定義數組的長度] --forall 表示一次執行一批sql
execute immediate [帶綁定變量的目標sql] using [對應綁定變量的輸入值]
PLSQL中使用批量綁定的范例代碼為如下所示,
declare
cur_emp sys refcursor;
ve_sql varchar2(4000);
expe namelist ie table of varchar2(10);
enames namelist;
CN_BATCH_SIZE constant pls_integer :=1000;
begin
vc_sql :='select ename from emp where empno>:1';
open cur_emp for vc_sql using 7900;
loop
feteh cur_emp bulk collect into enames linit CN_BATCH_SIZE;
for i in 1..enames.count loop
dbms_output.put_line(enames(i));
end loop;
exit when enames.count< CN_RATCH_SIZE;
end loop;
close cur_emp;
end;
/
1709
index fast full scan 會掃描所有的索引葉子塊
1723
對於目標soL(即即 seleet count(*) fom tl where object_id between :x and :y)而言,其where條件的selectivity
和Cardinality的計算公式為如下所示示
Cardinality=NUM_Rows*Selectivity
selectivity=((y-x)/(HIGH_VALUE-LOW_VALUE)+2/NUM_DISTINCT)*Nu11_Adjust
Nu11_Adjust=(NUM ROWS-NUM_NULLS)/NUM_ROWS
NUM_Rows表示目標列所在表的記錄總數
LOW_VALUE 目標列的最小值
HIGH_VALUE 目標列的最大值
NUM_DISTINCT 目標列的 distinct值的數量
NUM_NULLS 目標列的NULL列的數量
從如下查詢結果可以看到,對應於上述計算公式的LOW_VALUE的值為C103,
HIGH_VALUE的值為C309395E,NUM_DISTINCT的值為72,387,NUM_NULLS的值為2;
select 1ow_value,high_value,num_distinct,num_nulls from dba_tab_col_statistics
where owner='SCOTT' and table_name='T1' and column_name='OBJECT_ID';
LOW_VALUE HTCH_VATUE NUM_DTSTINCT NUM_NULLS
----------------------------------------------
c103 C309395e 72387 2
從如下查詢結果可以看到,HIGH_VALUE的值C309395E實際上就等於85,093;
SQL> select max(object_id),dump(min(object_id),16) from ti ;
MAX(OBJECT_ID) MAX (OBJECT ID) DUMP(MAx(OBJECT_ID),16)
85693 Typ=2 Len=4: c3,9,39,5e
從如下查詢結果可以看到,LOW_VALUE的值C103實際上就等於2
SQL> select min(object_id),dump(min(object_id),16) from ti ;
MIN(OBJECT_ID) MIN (OBJECT ID) DUMP(MAx(OBJECT_ID),16)
2 Typ=2 Len=2: c1,3
查詢到的 NUM_ROWS、LOW_VALUE、HIGH_VALUE、NUM_DISTINCT、NUM_NULLS 和 x、y的值代入計算公式。
2111 刪除sql的 shared cursor
exec sys.dbms_shared_pool.purge([address],[hash_value],'c');
2215
select tab.ADDRESS,tab.BIND_NAME,tab.POSITION,tab.DATATYPE,tab.MAX_LENGTH from v$sql_bind_metadata tab
2217 批量綁定時如何處理錯誤
bulk_errors exception;
paragma exception_init(bulk_errors,-24381);
type typ_errorindex is table of number index by binary_integer;
errorindexs typ_errorindex;
type typ_errorcode is table of varchar2(50) index by binary_integer;
errorcodes typ_errorcode;
exception
when bulk_errors then
for i in 1..sql%bulk_exceptions.count() loop
errorindexs(j):=sql%bulk_exceptions(j).error_index;
errorindexs(j):=-sql%bulk_exceptions(j).error_index;
0934
Oracle10g及后續的版本中,Oracle會自動收集直方圖統計信息。直方圖統計信息 是對於單個列的
0946
v$sql_cs_statistics 用於顯示指定 child cursor中存儲的runtime統計信息
v$sql_cs_selectifity 用於顯示指定的、已經被標記為 Bind Aware的 Child Cursor中存儲的含綁定變量的謂詞條件對應的可選擇率的范圍
0956
收集直方圖統計信息
exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'T1',estimate_percent=>100,cascade=>true,method_opt=>'for all columns size auto',no_invalidate=> false);
dbs_tab_col_statistics
1009
再次以目標SQL對應的SQL_ID去查詢視圖VSSQL:
soL> select child_number,executions,buffer_gets,is bind_sensitive bs,is bind_aware ba,
is shareable SH,plan_hash_value from v$seql where sql id=179g1p919t7x4u”)
BUFFER GETS BS BA SH BLAN_HASH_VALUE
EXECUTIONS
CHILD NUMBER
1029
在目標列有Frequency類型直方圖的前提條件下,如果對目標列等值查詢條件,且在查詢條件的輸入值等於該類的實際值時,謂詞條件的可選擇率計算公式如下所示:
selectivity=Bucketsize /NUM_ROMS
上述計算公式啟用了綁定變量就探,目標列有Frequency類型的直方圖,對日標列添加等值查詢條件,且
查詢條件的輸入值等於該列的某個實際值時的計算。
NUM_ROWS 表示目標列所在表的記錄數。
BucketSize表示目標列的某個實際值所對應的記錄致。
1051 -一定得搞清楚 child_number 可以根據sql_id 找到該sql所有的 child_number
child curor的可選擇率范圍
select child_number,predicate,range_id,low_high from v$sql_cs_selectivity where sql_id='xxxx';
v$sqlarea
1647
子查詢展開,執行效率
in 外部結果集條數 有 N,其實執行效率會把外部查詢全部執行,然后根據內部查詢的結果 去外部結果中 遍歷
/* no_merge(view_name) */ 不合並視圖
2124
參數star_transformation_enabled 用於控制是否啟用星型轉換
0939
在Oracle11gR2之前,把某個據不分區索引的狀態設為unusable后,會導致所有原本可以使用該局部分區索引的查詢語句都無法正常使用該局部分區索引
alter index index_name modify parartition p12 unusable; 索引的單個分區索引 失效
alter index index_name rebuild partition p12; 重建該分區索引,恢復可用狀態
1005
表移除
select ename from emp,dept where emp.deptno=dept.deptno;
表empde 列deptno 屬性為 not null,而在列deptno 和主表dept的主鍵列存在一個名為pk_deptno的外鍵。對於該外鍵而言,表emp是子表,表dept是主表。即 對於子表emp的列deptno而言,主表dept中一定存在與之對應的匹配記錄。因此
以上sql相當於 select ename from emp
博大精深的 cbo啊
1013
emp.deptno=dept.deptno(+) 外連接哦
1024
select * from emp where deptno in (10)
union all
select * from emp where mgr in (7782) and lnnvl(deptno in (10))
函數LNNVL 作用:排除 mgr in (7782) and deptno in (10)這種情形
1122
awr sql report
stat_name statement_total per_exection
elapsed_time(ms) 637922
exections 66(次)
buffer gets 222222(個)
1439
一定要記住哦,對系統內部表使用dbms_stats包收集統計信息哦。如下
exec dbms_stats.gather_table_stats(ownname=>'SYS',tabname=>'X$BH');
從Oracle10g開始,創建索引之后Oracle會自動收集目標索引的統計信息
刪除索引的統計信息
analyze index index_name delete statistics;
對表t2收集統計信息,並且是 以 估算模式,采樣比例是 15%
analyze table t2 estimate statistics sample 15 percent for table;
對表t2收集統計信息,並且以 計算模式
analyze table t2 compute statistics for table;
對表t2 的列 col1,col2 收集統計信息,以 計算模式
analyze table t2 compute statistics for column col1,col2;
記住哦,對同一個對象 新的analyze命令會擦除 之前的analyze的結果
同時對表t2和 列 col1、col2 收集統計信息
analyze table t2 compute statistics for table for columns col1,col2;
以計算模式對索引 idx02 收集統計信息
analyze index idx02 compute statistics;
一次性的以 計算模式 收集表t2、表t2的所有列和表t2上的所有索引的統計信息,如下:
analyze table t2 compute statistics;
以估算模式對條t2收集統計信息,采樣比例是15%
exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'T2',estimate_percent=>15,method_opt=>'FOR TABLE',cascade=>false);
刪除表t2、所有列、所有索引的統計信息
exec dbms_stats.delete_table_stats(ownname=>'SCOTT',tabname=>'T2')
一次性以計算模式收集表t2、所有列、所有索引的統計信息
exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'T2',ESTIMATE_PERCENT=>100,CASCADE=TRUE);
1542
analyze 命令不能正確收集分區表的統計信息,而DBMS_STATS包
1548
dbms_stats包可以 並行收集表的統計信息哦 degree
exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'T2',cascade=>true,estimate_percent=>100,degree=4);
dbms_stats只能收集與cbo相關的統計信息,而與cbo無關的額外信息無法收集。比如 行遷移/行鏈接。analyze 可以哦
比如:analyze table table_name list chained rows into xxx;
analyze index index_name validate structure;
1621
數據典中的字段NUM ROWS存儲的就是目標表的記錄數,目標表的記錄數是計算結果集的基礎,而結果集的Cardinality則往往直接決定了CBO計算的成本值。
數據字典中的字段BLOCKS存儲的就是目標表表塊的數量,即目標表的數據所占用數據塊的數量,目標表表塊的數量會直接決定CBO計算出來的對目標表做全表掃描的成本,目標表表塊的數量越大,則對目標表走全表掃描的成本值就會越大。
數據字典中的字段AVG_ROW_LEN存儲的就是目標表的平均行長度。平均行長度的計算方法是用目標表的所有行記錄所占用的字節數(不算行頭)除以目標表的總行數,它可能會被Oraele,用來計算目標表對應的結果集所占用內存的大小
1650
--2.查找表的歷史統計信息
select obj.object_name, oth.savtime, oth.rowcnt, oth.analyzetime,oth.blkcnt,oth.avguln
from sys.WRI$_OPTSTAT_TAB_HISTORY oth, dba_objects obj
where oth.obj# = obj.object_id and obj.object_name='EMP' --請修改表名字
order by oth.analyzetime desc nulls last;
1507
上述數據字典中的字段CLUSTERNG FACTOR.存儲的就是目標索引的聚簇因子,聚族因子是指按照然索引鍵值排序和存儲於對應表中的數據行的存儲順序的相似程度。
上述數據字典中的字段DiSTRNCT KEYS存儲的就是目標索引的索引鍵值的disinct值的數量。對於唯一性索引而言,在沒有NULL值的情況下,DISTINCT.KEYS的值就等手對應表的記錄數。
上述數據字典中的字段AVG_LEAF_BLOCKS_PER_KEY存儲的就是目標索引的每個distinct索引鍵值所占用的葉子塊數量的平均值,對於唯一性索引而言,AVG_LEAF_BLOCKS_PER_KEY顯然只會是1。
上述數據字典中的字段AVG_DATA BLOCKS_PER_KEY存儲的就是目標索引的每個distnet索引鍵值所對應表中的數據行所在數據塊數量的平均值。
上述數據字典中的字段NUM_ROWS存儲的就是目標索引的索引行的數量。
修改索引的聚簇因子 clstfct
exec dbms_stats.set_index_stats(ownname=>'owner_name',indname=>'index_name',clstfct=>1000,no_invalidate=>false);
hist_head$
2125
執行計划中Rows列的值表示CBO評估出來的對應執行步驟所返回結果集的行數
cardinality=NUM_ROWS*selectivity
Nul1_Adjust=(NUM——ROWS-NUM_NULLS)/NUM_ROWS
selectivity=((HTGH_VALUE-VAL)/(HTCH_VALUE-Lo_VALUE))*Null——Adjust
2140
dba_hist_sqlstat
2154
檢查目標表中 列的統計信息
select t1.low_value,t1.high_value from dba_tab_col_statistics t1 where t1.table_name='EMP' and column_name='EMPNO'
取出 low_value
SQL> var temp date;
SQL> exec dbms_stats.convert_raw_value('low_value',:temp);
2208
直方圖 Histgrm是一種特殊的列統計信息,詳細描述了目標列的數據分布情況。存儲在數據字典基表 histgrm$;專門為了准確評估分布不均勻的目標列的可選擇率、結果集的cardianlity。詳細描述了目標列的數據分布情況,並將分布情況記錄在數據字典里。
2228 對 列收集直方圖
exec dbms_stats.gather_table_stats(ownname=>'owner_name',tabname=>'table_name',method_opt=>'for columns size auto column_name',cascade=>true);
'for columns size auto column_name' 表示對目標表的列 column_name 收集直方圖統計信息,auto 的含義是指讓Oracle自行決定到底是否對列column_name收集的直方圖是哪種類型的直方圖
oracle會關注目標表的某個列的使用情況,記錄在 col_usage$
select * from col_usage$;
20170424
0933
dba_tab_col_statistics
dba_tab_histograms 表的直方圖相關信息
0935
文本型 ‘1’ 轉換為 浮點數
select dump(1,16) from dual;
typ=96 len=1:31
0x31右邊補0一直補到15個字節的長度,再轉換為十進制數
select to_number('31000000000000000','XXXXXXXXXXXXXXXXX') from dual;
0948
刪除列id上的直方圖統計信息
exec dbms_stats.gather_table_stats(ownname=>'owner_name',tabname=>'table_name',method_opt=>'for columns size 1 id',cascade=>true);
注意此處的 1 表示對列 id收集直方圖時使用的bucket的數量為1
1010
DBMS_STATS包中上述存儲過程的輸入參數METHOD_OPT可以接受如下的輸入值:
FOR ALL [INDEXED | HIDDEN] COLUMNs (size_clause]
FOR CoLUMNS [size clause] column|attribute [size clause] [,columnlattzibute
[size clause]..
其中的size clause必須符合如下的格式:
SIZE{integer | REPEAT | AUTo | SKEWONLY}
size clause子句中各選項的含義如下所述。
* interer.直方圖的Bucket的數量,必須是在1~254的范圍內,1表示刪除該目標列上的直方圖統計信息
*REPEAT;只對已經有直方圖統計信息的列收集宜方圖統計信息,
*auto Oracle 自行決定是否對目標列收集直方圖統計信息,以及使用哪種類型的直方圖統計信息
*SKEWONLY:只對數據分布不均衡的列收集直方圖統計信息。
1027
select /*+cursor_sharing_exact_demo */ count(*) from t;
v$sqlarea version_count
1034
直方圖統計信息實際上可以影響shared cursor是否能被共享
1041
null_adjust=(num_rows - num_nulls)/num_rows
density(密度、基數)=1 / (2* num_rows * null_adjust)
dba_tab_histograms
1101
select power(3296,2) from dual;
POWER(3296,2)
-------------
10863616
1122
以下三忌:
如果目標列的數據時均勻分布的,比如 主鍵列、唯一索引的列,根本不需要對這些列收集直方圖統計信息
對於那些從沒有在sql語句的where條件中出現的列,不管數據分布是否均勻,都無需對其收集直方圖統計信息
直方圖統計信息可能會影響shared_cursor的共享
在配置oracle10g引入的自動統計信息收集作業的時候,需要特別注意對直方圖統計信息的收集策略
1238
全局統計信息對CBO來說是非常重要的,針對分區表的sql,除非查詢條件先定了帶訪問的數據只在部分分區上,飛則大部分情況下都需要全局統計信息才能得到正確的執行計划
只能由 dbms_stats來收集
1246
analyze命令對表t2以計算模式收集統計信息(計算模式會掃描目標對象的所有數據)
analyze table t2 compute statistics;
1249 查找某參數的默認值
select dbms_stats.get_param('granularity') from dual;
1252 刪除表的統計信息
exec dbms_stats.delete_table_stats(ownname=>'user_name',tabname=>'table_name')
1255
使用dbms_stats.gather_table_stats重新收集統計信息,參數granularity的值為 all,表示在t2的表級別、分區級別、子分區級別都收集全局統計信息
exec dbms_stats.gather_table_stats(ownname=>'owner_name',tabname=>'table_name',estimate_percent=>100,granularity=>'ALL');
1304
analyze table table_name delete statistics; 只會刪除子分區的統計信息
1307
analyze ... delete statistics.只級聯刪除子分區和分區的統計信息
1310
可以看到,ANALYZE…..DELETE STATISTICS命令只級聯刪除了子分區和分區上的統計信息
綜合上述測試結果我們可以發現,ANALYZE….DELETE STATISTiCS命令總是會刪除子分區的統計信
息,但是否能夠級聯刪除分區級/表級的統計信息則取決於相應級別的GLOBAL_STATS的值。
如分區表級/表級 的GLOBAL_STATS的值為YES,則不能級聯刪除;反之就可以級聯刪除。
但要注意的是,ANALYZE DELETE STATisTice命令不能跨級刪除統計信息,比如分區的GLOBAL STATIS的值為YER,而表級的
GLOBAL STATIS 的值為NO,則在使用ANALYZE…….DELETE STATISTiCS命令后表級的統計信息並不會被刪除。
另外,DBMS_STATS.DELETE_TABLE_STATISTICS 總是可以副除分區表上所有的三個級測的統計傳。
1316
最后我們來總結一下在Oradke數據庫中使用全局統計信息的注意事項。
(1)應使用DBMS_STATS包來對分區表收集全局統計信息。
(2)應使用DBMS_STATS包中的相關存儲過程(如DBMS_STATS.DELETE_TABLE_STATS)來刪除分區表的統計信息,盡量避免用ANALYZE命令,因為ANALYZE命令不一定能把分區表的統計信息刪除干凈
(ANALYZE命令可能會導致部分統計信息並沒有被刪除)。
(3)收集分區表的統計信息時應使用一致的GRANULARITY參數。如果不使用一致的GRANULARITY
參數,比如開始用ALL,過一段時間用GLOBAL或PARTTTION,這樣可能會導致在某些級別上的統計信息
是過時的、不准確的。
(4)由於ANALYZE命令只在最低一級收集統計信息,而高一級的統計信息則是由下級統計信息匯總和
推導而來的,因此盡量不要使用ANALYZE命令來對分區表收集統計信息,特別是不要將ANALYZE命令與
DBMS_STATS包聯合使用在同一張分區表上,否則可能會導致該表在某些級別上的統計信息是過時的、不准確的。
1325
動態采樣有如下兩個方面的作用。
(1)Oracle稱如果使用了動態采樣,則不管SQL語句中各列有什么樣的關聯關系,在大多數情況下,CBO
都可以相對准確地估算出整個where條件的組合可選擇率,進而能相對准確地估算出返回結果集的Cardinality
(2)有一些應用在執行的過程中會創建一些臨時表,然后會往這些臨時表里插入一些中間結果,接着將這
些臨時表用於查詢等操作,在執行完畢后會把這些臨時表Drop掉或者Truncate其中的數據。這里的問題是
當這些臨時表參與查詢等操作的時候,它們是沒有統計信息的,這種情況下采用的執行計划有可能是低效的
其至是錯誤的。而動態采樣就可以在一定程度上解決這種因臨時表沒有統計信息而導致CBO選錯執行計划的
問題。
1331
參數OPTIMIZER_DYNAMIC_SAMPLING的值及含義
level值及含義
1338
在“5.4.2聚族因子的含義及重要性”中提到索引范圍掃描的成本計算公式為:
IRS Cost=I/O Cost +CFU Cost
I/O cost =Index Access I/o cost +Table Access I/o cost
Index Access I/O Cost =BLEVEL+CEIL(#LEAF_BLocKS *IX_SEL)
Table Access I/0 Cost=CEIL(CLUSTERING_FACTOR*IX_SEL_WTTH_FTLTERS)
1400
位表t2中有關聯關系的列 n1 和 n2 創建一個組合咧
declare
cg_name varchar2(30);
begin
cg_name:=sys.dbms_stats.create_extended_stats('SCOTT','T2','(n1,n2)');
dbms_ouptput.put_line(cg_name);
end;
/
1413
select col#,intcol#,distcnt,minimum,maximum,density from sys.hist_head$;
1416
exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'T2',method_opt=>'for columns(n1,n2) size auto',estimate_percent=>100);
1436
dbms_stats.gather_system_stats 收集數據庫服務器的統計信息
dbms_stats.delete_system_stats 刪除數據庫服務器的統計信息
1. dbms_stats.gather_system_stats('start');開始收集系統統計信息
2. 正常使用系統
3. dbms_stats.gather_system_stats('stop'); 停止收集系統統計信息
1452
系統統計信息會存儲在表AUX_STATSS里。執行DBMS_STATS.GATHER_SYSTEM_STATS收集系統統計
信息的時候,Oracle會在AUX STATSS里記錄如下四個方面的信息。
·CPU的主頻,單位是MHz(兆赫茲)。
·單塊讀的平均耗費時間,單位是ms(毫秒)。
·多塊讀的平均耗費時間,單位是ms(毫秒)。
·單次多塊讀所能讀取的數據塊的平均值。
Orace 會記錄目標數據庫所在的數據庫服務器上的單次多塊讀所能讀取的數據塊的平均值,這對計算
全表掃描的成本帶來了重大影響,因為在這種情況下MBDMSor 實際上就和
DB_FILE_MULTIBLOCK_READ_COUNT的值沒有關系了。
1457
sys.all_parameters
1504
oracle 11.2.0.1
12:51:37 idle> show parameter multiblock;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_file_multiblock_read_count integer 128
1522
全表掃描 多快讀(168)
index range scan 單塊讀(1)
1524
修改單塊讀的平均耗費時間為 10ms
exec dbms_skats.set_system_stats('sreadtim',10);
修改多塊讀的平均耗費時間為 20ms
exec dbms_skats.set_system_stats('mreadtim',20);
1540
dbms_stats包里的存儲過程dbms_stats.gather_dictionary_stats、bms_stats.delete_dictionary_stats 分別用於一次性收集、刪除所有數據字典統計信息
1554
DBMS_STATS包里的存儲過程GATHER_FIXED_OBJECTS STATS和DELETE_FIXED_OBJECTS_STATS
專用於一次性收集和刪除所有的內部對象統計信息。
上述兩個存儲過程的用法為如下所示。
一次性地收集所有XS表的內部對象統計信息:
sqL> exec dbms_stats.gather_fixed_objects_stats();
PL/SoL procedure successfully completed
一次性地刪除所有X$表的內部對象統計信息:
sql> exec dbms_stats.delete_fixed_objects_stats();
BL/SoL procedure successfui1y compieted nnnnnniint
收集單個x$(x$kccrsr) 表的對象統計信息
exec dbms_stats.gather_table_stats(ownname=>'SYS',tabname=>'X$KCCRSR',estimate_percent=>100,cascade=>true);
刪除單個x$(x$kccrsr) 表的對象統計信息
exec dbms_stats.delete_table_stats(ownname=>'SYS',tabname=>'X$KCCRSR');
1656
查看自動收集統計信息的job運行狀態
16:50:01 idle> select actual_start_date,job_name,status from (select * from dba_scheduler_job_run_details where job_name='GATHER_STATS_JOB' ORDER BY LOG_DATE DESC) where rownum <4;
no rows selected
1725
sys.mon_mods_all$
如果想馬上看到目標表的insert 、update、delete,需要執行以下 dbms_stats包中的存儲過程flush_database_monitoring_info;
exec dbms_stats.flush_database_monitoring_info();
select obj#,inserts,updates,deletes ,flags from sys.mon_mods_all$ where obj#=object_id;
1733
禁掉自動統計信息收集作業
exec dbms_scheduler.disable('GATHER_STATS_JOB');
只對存在直方圖統計信息的列才收集直方圖統計信息
exec dbms_stats.set_param('METHOD_OPT','FOR ALL COLUMNS SIZE REPEAT');
2135
盡管如此,我們還是推薦一個統計信息收集作業采樣比例的初始值;
對於orede 11g及其以上的版本,收集統計信息的采樣比例建議采用DBMS_STATS.AUTO_SAMPLE_SIZE.
Oracle 110中的AUTO_SAMPLE_SIZE采用了全新的哈希算法,它既能保證在較短的時間內執行完又能保證收集到的統計信息
接近采樣比例為100%時的質量)。
如果是Oracle 10g,繼續采用DBMS_STATS.AUTO_SAMPLE_SIZE就不太合適了,因為這個自動采樣比例在Oracle 10g里是非常小的一個
Oracle 10g中將采樣比例的初始值設為30%,然后根據目標SQL的實際執行情況再做調整
如果是Oracle9i,我們建議將采樣比例的初始值也設為30%,然后根據目標SQL的實際執行情況再做調整
(5)建議使用DBMS_STATS包來對分區表收集全局統計信息,並且收集分區表的統計信息時應使用一致致
的GRANULARITY參數,全局統計信息的收集方法和注意事項請見“5.6全局統計信息”。
(6)建議要額外收集系統統計信息,但系統統計信息收集一次就夠了,除非系統的硬件環境發生了變化,
系統統計信息的收集方法請見“5.9系統統計信息”
(7)建議要額外收集X$表的內部對象統計信息,但僅僅是在明確診斷出系統已有的性能問題是因為x$
表的內部對象統計信息不准的情形下,對於其他情形就不要收集了。X$表的內部對象統計信息的收集方法和
注意事項請見“5.1l內部對象統計信息”。
2141
適用於Oracle 11g及其以上的版本
EXEC DBMS_STATS.GATHER_TABLE_STATS(
OWNNAME=>'SCHEMA_NAME',
TABNAME=>'TABLE NAME',
ESTIMATE PERCENT=>DBMS STATS,AUTO_SAMPLE_SIZE,
CASCADE=>TRUE,
METROD_OPT=>'FOR ALL COLUMNS SIZE REPEAT'):
2144
鎖住表的統計信息
dbms_stats.lock_table_stats
2148
聚簇因子的大小對CBO判斷是否走相關的索引至關重要
20170426
0951
dbms_xplan.display_cursor(null,null,'ALLSTATS LAST')
0959
只要在sql中啟用 hint,那么默認啟用的cbo
1012 hint格式
hint 中第一個星號 (*)和加號(+)之間不能有空格
hint zhong jiahao (+)和具體的hint內容之間可以有空格,也可以沒有空格,通常都有
hint中的具體內容可以使單個hint,也可以是多個hint的組合。如果是后者,則各個hint見至少需要一個空格來彼此分隔
hint 必須緊跟 select、update、delete、insert、merge
hint 中不能跟schema哦
hint 如果后面 表指定了別名,全表掃描時 必須在hint中指定 別名
1104
_optimzer_ignore_hints 忽略sql中的 hint提示
觸發器執行該操作
create or replace trigger ignore_hints_on_logon
after logon on database
begin
execute immediate 'alter session set "_optimzer_ignore_hints"=true';
end;
/
1120
對於非分區索引而言,索引范圍掃描或者索引全掃描都不可能並行執行
1126
/*+ use_hash(emp) */ hash連接的hint
hash連接的被驅動表應該是數據量最多的那個表
hash連接只使用於 等值連接查詢
1210
cardinality(dept 100) 表示掃描表dept得到的結果集的 cardinality設為100
1221
hint no_merge 禁用查詢轉換
1227
組合hint中各個hint間不要使用逗號“ ,” 來彼此分割(應該使用空格來彼此分隔)
1235 all_rows
讓優化器啟用cbo,而且在得到目標sql的執行計划時會選擇那些吞吐量最佳的執行路徑。吞吐量最佳 值資源消耗量最小(比如 i/o cpu等硬件資源)
1320
INDEX_FFS 前提條件:select語句中所有的查詢列都在目標索引中,即通過掃描目標索引就可以得到所有的查詢咧而不用回表
INDEX_JOIN 前提條件:select語句中所有的查詢列都在目標表的多個目標索引中,即通過掃描這些索引就可以得到所有的查詢列而不需要回表
1327
INDEX_FFS 執行計划
INDEX_JOIN 執行計划
1359
sou> select /*+ rule */count(*)from tii ;
Plan hash value:3110199320
rd I operation
0 I SBLECT STATEMENT
SORT AGGREGATB
I PX COORDINATOR
SORT AGGREGATE
PX BLOCR ITBRATOR I
TABLE ACCESS FULLI T1
一省略顯示部分內容
可以看出,上述SQL的執行計划已經從之前的串行全表掃摘表T1變為並行全表掃描花型,8
新2ea”這表示上述SQL在解析時使用的是CBO,這也驗證了之前的觀點:如果日行
為用於並行執行,就意味着其中的RULE Fmnt會失效,此此時Once會自動啟用cBo
1431
PARALLEL hint的格式有如下4中:
/*+ PARALLEL */
/*+ PARALLEL(AUTO) */ 此處指定 auto,那么並行度 可能為1.因此不一定會用到 parallel
/*+ PARALLEL(MANUAL) */
/*+ PARALLEL(指定的並行度) */
v$pq_slave
1451
NO_PARALLEL HINT
1521
driving_site(目標表)【強制操作在目標表執行】 原則 盡可能的減少本地節點和遠程節點之間網絡傳輸的數據量
select /*+ driving_site(t)*/ col1,col2 from remote_tab@dblink_name
1533
直接路徑加載數據一定要記得啟用 parallel dml
1536
/*+ APPEND_VALUES */
0937
檢查綁定變量的傳入值
SQL> select
snap_id,
dbms_sqltune.extract_bind(bind_data,1).value_string bindi,
dbms_sqltune.extract_bind(bind_data,2).value_string bind2,
dbms_eqltune,extract_bind(bind_data,3).value_string bind3
from dbs_hist_sqlstat
where sql_id='&sql id
order by snap_id;
Enter value for sql_id:ay29xy01d36yb
old 7:where sql_id='&sql_id'
new 7:where sgl_id='ay29xy01d36yb'
0945
執行計划中 的
Rows
30M 此處30M 也就是 30*1000*1000 =3000萬 哦
0955
取樣默認 5%
1108
parallel hint /*+ parallel_execution_demo_1 */
serial hint /*+ serial_execution_demo_1 */
1114
強制啟用dml操作的並行
alter session force/enable parallel dml;
僅僅修改表的並行度和僅僅使用並行hint,不能真正並行執行dml。 記住!!!
1127
exec dbms_stats.gather_table_stats(ownname(用戶名)=>'user_name',tabname(表名)=>'table_name',cascade=>true,estimate_percent=>100,degree(並行度)=>4 )
1255
kxfqcdty 就是列類型
kxfqcplen 就是列的最大長度
1324
dba_tab_partitions 分區以 object的形式存在
1355
granule 粒度
1403
db file scattered read 數據文件散列讀
1409
v$bh.dirty (y 臟塊;n 非臟塊)
1412
parallel 會產生一個 parallel query checkpoing
“DBWR parallel query checkpoint buffers written”
1423
bbed
1516
要想使用並行 dml ,要么使用 alter session force parallel dml 要么使用 alter session enable parallel dml 和加了hint 的dml語句
1922
alter table table_name parallel n;
alter index index_name parallel n;
procedure 中 執行 ddl 語句,例如:
execute immediate 'alter session force parallel dml';
commit/rollback;
execute immediate 'alter session disable parallel dml';
連接池中的連接 會被重復使用哦
0915
v$tracsaction的 列 used_ublk 表示用到的 undo_block的總數
used_urec 表示用到的 undo record的總數
cr_get 表示消耗的邏輯讀(consistent gets)的總數
只需監控v$tracsaction的used_urec的值的遞增情況就可以知道 sql的並行執行進度
1018
單鍵值索引:
where col1 is not null; null 值 不會使用索引的 切記
復合鍵值索引:
where col1 is not null; null 值 會使用索引的 切記
1031
where col like '%aaa%' 這種情況不走索引
1049
在本書的“第2章Oracle里的執行計划”中我們已經提到,如果目標SQL的執行計划還在Shared Pool
中,那就可以使用腳本display_cursor_9i.sql和存儲過程printsql來得到其真實的執行計划和資源消耗,如果目
標SOL的執行計划已經被age out出 Shared Pool了,那么我們可以執行DBMS_XPLAN.DISPLAY_AWR或者使用AWR SQL報告(獲得AVR SQL報告的途徑通常是手工執行腳本
SORACLE_HOME/rdbms/admin/awrsqrpt.sql,適用於Oracle 10g及其以上的版本)和Statspack SQL報告(獲得
Statspack SQL報告的途徑通常是手工執行腳本SORACLE_HOME/dbms/admin/sprepsql,適用於Oracle9i及其
以上的版本)來得到其歷史執行計划和資源消耗(DBMS_XPLAN DISPLAY_AWR僅能查看目標SQL的歷史
執行計划)。當我們得到了Top SQL的執行計划和資源消耗后,通常還會執行腳本sosibxt來獲得上述Top SooL
中相關對象的統計信息來輔助診斷,甚至還可能會對上述Top SL.使用10046/10053等事件,綜合上述內容后
你可以分析出此Top SOL的執行計划是否合理,是否存在性能問題了。display_cursor_9i.sql、printql和
sosi.txt 都可以通過我網站上的Books專欄下載,網址為http /www dbsnake.net/books
1106
計算牟表的數據量
sum(bytes)/1024/1024 dba_segments
計算某個字段的 可選擇率
select count(col_name),count(distinct col_name) from table_name
--進程在等待什么
select t.EVENT#,t.PROGRAM,t.SECONDS_IN_WAIT,t.STATE from v$session t where t.USERNAME='' and t.status='ACTIVE';
--1129
select t.TABLE_NAME,t.NUM_ROWS,t.BLOCKS,t.AVG_ROW_LEN,t.PARTITIONED,t.NUM_ROWS*t.AVG_ROW_LEN/1024/1024/0.9 est_M from dba_tables t
