按腳本新建兩張表T1,T2表中數據存儲以下: java
當對兩張表進行相同的查詢操做時,T1表會使用索引,但T2表不會它將進行全表掃描。sql
select * from t1 where id=10;
select * from t2 where id=10;
複製代碼
這主要是由於T1表的聚簇因子的值接近表的表塊數量,而 T2表的聚簇因子的值接近表中數據數量。 若是聚簇因子的值接近表的表塊數量,則說明目標索引索引行和存儲於對應表中數據行的存儲順序類似程度很是高。這就意味着Oracle走索引範圍掃描後取得目標rowid再回表訪問對應表塊中的數據時,相鄰的索引行所對應的rowid找到的表數據很可能處於同一表塊中。即Oracle在經過索引行記錄的rowid回表第一次讀取對應的表塊並將該表塊緩存在buffer cache中後,當再經過相鄰索引行記錄的rowid回表第二次去讀取對應的表塊時就不須要再產生物理I/O了,由於這兩次訪問的是同一個表塊,而這個表塊已經緩存在buffer cache中了。 若是聚簇因子的值接近表的記錄數,則說明目標索引索引行和存儲於對應表中數據行的存儲順序類似程度很是低,這就意味着Oracle走索引範圍掃描取得rowid再回表訪問對應表塊的數據時,相鄰的索引行所對應的rowid很可能不處於同一表塊中,說明Oracle每次都要讀對應的表塊,每次都產生物理I/O。數據庫
經過B樹索引訪問數據的過程:先訪問相關的B樹索引,而後根據訪問該索引後獲得的ROWID再回表訪問相應的數據行記錄。 這裏訪問相關的B樹索引和回表都須要消耗I/O,這意味着訪問索引的成本由兩部分組成:一部分是訪問相關的B樹索引的成本(從根節點定位到相關的分支塊,再定位到相關的葉子塊,最後對這些葉子塊進行掃描);另外一部分是回表的成本(根據ROWID再回表掃面對應的數據行所在數據塊)緩存
適用於全部類型的B樹索引。所謂的索引全掃描是指掃描目標索引的全部葉子塊的全部索引列。這裏須要注意索引全掃描須要掃描全部的葉子塊但不意味着須要掃描全部的分支塊。Oracle在作索引全掃描時只須要經過訪問必要的分支塊定位到位於該索引最左邊的葉子塊的第一行索引行就能夠利用該索引葉子塊之間的雙向指針鏈表,從左到右依次順序掃描該索引全部葉子塊的全部索引行了。 由於索引是有序的因此經過索引全掃描獲得的結果也是有序的便可以免排序操做。 函數
由於索引全掃描獲得的結果是有序因此不能並行執行,並且只能單塊讀。oop
注意:索引列不能容許null,不然將不會走索引全掃描。優化
須要注意當使用delete刪除數據時,高水位會保持不變就是說全表掃描所需的時間會差很少。 ui
create index idx_t3 on test3(object_id,0);
複製代碼
create index idx_t3_tm on test3(trunc(created));
複製代碼
create index idx_t3_nm on test3(reverse(object_name));
複製代碼
create index idx_t3_un on test3(owner||'_'||object_type);
複製代碼
create index idx_t3 on test3(object_name,object_id);
select t.* from edcs.test3 t where t.object_id > 1 and t.object_name='I_IND1';
複製代碼
若是兩張表(T1和T2表)在作表連接時使用的是排序合併連接,則Oarcle會按下面的步驟執行:spa
一般狀況下,排序合併連接的效率不如哈希連接,但哈希連接只能使用等值連接條件,而排序合併連接能夠用於非等值連接。排序合併連接由於須要對數據進行排序當數據量很大時排序是很耗I/O的。3d
可使用use_merge()提示指定走排序合併連接。
若是兩張表(T1和T2表)在作表連接時使用的是嵌套循環連接,則Oarcle會按下面的步驟執行:
經過上面的描述咱們能夠看出,驅動表的結果集每每比較小,若是在被驅動表的連接上又存在選擇性較好的索引,那麼嵌套循環執行效率就會很是高。 嵌套循環還有一個優點就是它能夠實現快速響應,即它能夠第一時間將已連接過且符合連接條件的數據先返回,而不用等全部的連接操做都完成在返回。 可使用use_nl()提示指定走嵌套循環連接。
哈希連接是一種兩個表在作表連接時主要依靠哈希運算來獲得連接結果集的表連接方法。
在Oracle7.3以前數據庫經常使用的錶鏈接方法主要是排序合併連接和嵌套循環連接兩種,但這兩種方法都有各自明顯的缺陷。對於排序合併連接,若是兩個表在施加了目標SQL中指定的謂語條件後獲得的結果集很大且須要排序則排序合併連接的執行效率必定不高;對於嵌套循環連接若是驅動表對應的驅動結果集很大,即便在被驅動表的連接列上存在索引效率也是很低。爲解決上面的問題在Oracle7.3之後引入了哈希連接。但它只適用於等值的連接條件。
可使用use_hash()提示指定走哈希連接。
若是兩張表(T1和T2表)在作表連接時使用的是笛卡爾連接,則Oarcle會按下面的步驟執行:
--建表
create table test1 as (select trunc((rownum-1)/100) id,rpad(rownum,100) t_pad from dba_source where rownum<=10000);
create table test2 as (select mod(rownum-1,100) id,rpad(rownum,100) t_pad from dba_source where rownum<=10000);
--建索引
create index idx_t1 on test1(id);
create index idx_t2 on test2(id);
--表分析的方法
analyze table test1 compute statistics for table ;
analyze table test2 compute statistics for table ;
--索引分析的方法
analyze index idx_t1 compute statistics ;
analyze index idx_t2 compute statistics ;
--查看統計信息
SELECT A.INDEX_NAME, B.NUM_ROWS, B.BLOCKS, A.CLUSTERING_FACTOR
FROM USER_INDEXES A, USER_TABLES B
WHERE A.INDEX_NAME IN ('IDX_T1','IDX_T2')
AND A.TABLE_NAME = B.TABLE_NAME;
select count(1) from test1 where id=10;
select count(1) from test2 where id=10;
select count(1) from test1 ;
select count(1) from test2 ;
select * from edcs.test1 where id=10;
select * from edcs.test2 t where id=10;
create table test3 as select * from dba_objects;
analyze table edcs.test3 compute statistics for table ;
create index idx_t3 on test3(object_id);
analyze index idx_t3 compute statistics;
create index idx_t3_tm on test3(created);
analyze index idx_t3_tm compute statistics ;
select count(1) from test3 t; --77230
--查看執行計劃
F5
set autot trace;
select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
--惟一索引
select * from tm_dcs_process_detail_config t where t.process_detail_id=2585378;
--範圍索引
select * from edcs.test3 t where t.object_id=15;
--索引全掃描
select t.process_detail_id from tm_dcs_process_detail_config t ;
--索引快速全掃描
select T.OBJECT_ID from TEST3 T;
select /*+ index_ffs(T IDX_T3) */ T.OBJECT_ID from TEST3 T;
--索引開發舉例
--存在null值走索引的方法
select rowid ,t.* from test3 t where t.object_id is null;
drop index idx_t3;
create index idx_t3 on test3(object_id,0);
analyze index idx_t3 compute statistics ;
--函數索引
select * from test3 t where trunc(created)>=date'2011-09-16';
drop index idx_t3_tm;
create index idx_t3_tm on test3(trunc(created));
analyze index idx_t3_tm compute statistics ;
--%使用索引
create index idx_t3_nm on test3(object_name);
select * from test3 t where t.object_name like '%CON1';
drop index idx_t3_nm;
create index idx_t3_nm on test3(reverse(object_name));
analyze index idx_t3_nm compute statistics ;
select t.* from test3 t where reverse(t.object_name) LIKE reverse('%CON1');
--兩列拼接走索引
select * from test3 t where owner||'_'||object_type ='SYS_CLUSTER';
create index idx_t3_un on test3(owner||'_'||object_type);
analyze index idx_t3_un compute statistics ;
--組合索引
create index idx_t3 on test3(object_id,object_name);
create index idx_t3 on test3(object_name,object_id);
select t.* from edcs.test3 t where t.object_id > 1 and t.object_name='I_IND1';
--錶鏈接方式
select * from tt_waybill_bak t1,tt_waybill_fee_bak t2 where t1.waybill_no=t2.waybill_no;
select /*+ use_merge(t1 t2) */ * from tt_waybill_bak t1,tt_waybill_fee_bak t2 where t1.waybill_no=t2.waybill_no;
select /*+ use_nl(t1 t2) */ * from tt_waybill_bak t1,tt_waybill_fee_bak t2 where t1.waybill_no=t2.waybill_no;
select /*+ use_hash(t1 t2) */ * from tt_waybill_bak t1,tt_waybill_fee_bak t2 where t1.waybill_no=t2.waybill_no;
select t1.*
from tt_waybill_fee_bak t1
where t1.waybill_no in
(select t2.waybill_no from temp3 t2);
select t1.*
from tt_waybill_fee_bak t1,temp3 t2
where t1.waybill_no = t2.waybill_no;
select t1.*
from tt_waybill_fee_bak t1
where t1.waybill_no in
(select /*+ no_unnest */ t2.waybill_no from temp3 t2);
--並行
select /*+ PARALLEL(T1 4)*/ t1.*
from tt_waybill_fee_bak t1
where t1.waybill_no in
(select t2.waybill_no from temp3 t2);
select t1.*
from tt_waybill_fee_bak t1
where t1.waybill_no in
(select t2.waybill_no from temp3 t2);
複製代碼
轉載自: 簡書 - 低至一折起