alter table tb2 modify empno number(4) not null;
翻到20W行
create index idxtb21 on tb2(empno);
select INDEX_NAME from dba_indexes where table_name='TB2';--驗證index建立起來
set autotrace on;
select distinct empno from tb2;--走index
select distinct ename from tb2 where empno=7934;--未走index
select distinct ename from tb2 where empno=7934;--hint后,也未走index
create index idxtb22 on tb2(ename);--難道和ename有關系?(按理說應該沒關系,建上吧)
select ename from tb2 where empno=7934;--還是不走index
重建index
alter index idxtb21 rebuild ;
1.alter index xxx rebuild [online];
是否加online,要看你的系統需求。因為不加online時rebuild會阻塞一切DML操作。
2.rebuild不是“將索引刪除然后再創建”。rebuild時不會為了排序去走fts,
而是遍歷舊索引,然后在臨時段中建立相應結構,完了后移到新索引中。
“將索引刪除然后再創建”,是最不好的方法。
select ename from tb2 where empno=7934;--還是不走index
真不懂了,難道只是因為我的優化器是CBO嗎?
或者是因為統計信息沒有刷新嗎?
或者莫非是因為我的表因為是翻起來的,里面的重復值比較多?(這個可能性非常大)
借網上文章看看后,還是不知原因,文章如下
oracle 優化器 不走索引原因
SQL優化器簡介 基於規則的優化器 。總是使用索引 。總是從驅動表開始(from子句最右邊的表) 。只有在不可避免的情況下,才使用全表掃描 。任何索引都可以 基於成本的優化器 。需要表、索引的統計資料 Analyze table customer compute statistics; Analyze table customer estimate statistics sample 5000 rows; 。表中設置並行度、表分區
優化器模式 rule模式 。總忽略CBO和統計信息而基於規則 choose模式 。Oracle根據情況選擇rule or first_rows or all_rows first_rows 模式 。基於成本,以最快的速度返回記錄,會造成總體查詢速度的下降或消耗更多的資源,傾向索引掃描,適合OLTP系統 all_rows模式 。基於成本,確保總體查詢時間最短,傾向並行全表掃描 例如: Select last_name from customer order by last_name;用first_rows時,迅速返回記錄,但I/O量大,用all_rows時,返回記錄慢,但使用資源少。
本文的目的: 1、說一說Oracle的Optimizer及其相關的一些知識。 2、回答一下為什么有時一個表的某個字段明明有索引,當觀察一些SQL的執行計划時,發現確不走索引的問題。 3、如果你對 FIRST_ROWS、 ALL_ROWS這兩種模式有疑惑時也可以看一下這篇文章。
開始吧:
Oracle在執行一個SQL之前,首先要分析一下語句的執行計划,然后再按執行計划去執行。分析語句的執行計划的工作是 由優化器(Optimizer)來完成的。不同的情況,一條SQL可能有多種執行計划,但在某一時點,一定只有一種執行計划是最優的,花費時間是最少的。 相信你一定會用Pl/sql Developer、Toad等工具去看一個語句的執行計划,不過你可能對Rule、Choose、First rows、All rows這幾項有疑問,因為我當初也是這樣的,那時我也疑惑為什么選了以上的不同的項,執行計划就變了?
1、優化器的優化方式
Oracle的優化器共有兩種的優化方式,即基於規則的優化方式(Rule-Based Optimization,簡稱為RBO)和基於代價的優化方式(Cost-Based Optimization,簡稱為CBO)。 A、RBO方式:優化器在分析SQL語句時,所遵循的是Oracle內部預定的一些規則。比如我們常見的,當一個where子句中的一列有索引時去走索引。 B、 CBO方式:依詞義可知,它是看語句的代價(Cost)了,這里的代價主要指Cpu和內存。優化器在判斷是否用這種方式時,主要參照的是表及索引的統計信 息。統計信息給出表的大小 、有少行、每行的長度等信息。這些統計信息起初在庫內是沒有的,是你在做analyze后才出現的,很多的時侯過期統計信息會令優化器做出一個錯誤的執行 計划,因些我們應及時更新這些信息。在Oracle8及以后的版本,Oracle列推薦用CBO的方式。
我們要明了,不一定走索引就是優的 ,比如一個表只有兩行數據,一次IO就可以完成全表的檢索,而此時走索引時則需要兩次IO,這時對這個表做全表掃描(full table scan)是最好的。
2、優化器的優化模式(Optermizer Mode)
優化模式包括Rule,Choose,First rows,All rows這四種方式,也就是我們以上所提及的。如下我解釋一下:
Rule:不用多說,即走基於規則的方式。
Choolse:這是我們應觀注的,默認的情況下Oracle用的便是這種方式。指的是當一個表或或索引有統計信息,則走CBO的方式,如果表或索引沒統計信息,表又不是特別的小,而且相應的列有索引時,那么就走索引,走RBO的方式。
First Rows:它與Choose方式是類似的,所不同的是當一個表有統計信息時,它將是以最快的方式返回查詢的最先的幾行,從總體上減少了響應時間。
All Rows:也就是我們所說的Cost的方式,當一個表有統計信息時,它將以最快的方式返回表的所有的行,從總體上提高查詢的吞吐量。沒有統計信息則走基於規則的方式。
3、如何設定選用哪種優化模式
a、Instance級別
我們可以通過在init.ora 文件中設定OPTIMIZER_MODE=RULE、OPTIMIZER_MODE=CHOOSE、 OPTIMIZER_MODE=FIRST_ROWS、OPTIMIZER_MODE=ALL_ROWS去選用3所提的四種方式,如果你沒設定 OPTIMIZER_MODE參數則默認用的是Choose這種方式。
B、Sessions級別
通過SQL> ALTER SESSION SET OPTIMIZER_MODE=;來設定。
C、語句級別
這些需要用到Hint,比如: SQL> SELECT a.userid, 2 b.name, 3 b.depart_name 4 FROM tf_f_yhda a, 5 tf_f_depart b 6 WHERE a.userid=b.userid;
4、為什么有時一個表的某個字段明明有索引,當觀察一些語的執行計划確不走索引呢?如何解決呢 ?
A、不走索引大體有以下幾個原因 ♀你在Instance級別所用的是all_rows的方式 ♀你的表的統計信息(最可能的原因) ♀你的表很小,上文提到過的,Oracle的優化器認為不值得走索引。 B、解決方法 ♀可以修改init.ora中的OPTIMIZER_MODE這個參數,把它改為Rule或Choose,重起數據庫。也可以使用4中所提的Hint.
補充:不走索引的原因,甚至加上hint 還不走索引,那可能是因為你要走索引的這列是nullable,雖然這列沒有空值。(將字段改為not null)
1、建立組合索引,但查詢謂詞並未使用組合索引的第一列,此處有一個INDEX SKIP SCAN概念。 2、在包含有null值的table列上建立索引,當時使用select count(*) from table時不會使用索引。 3、在索引列上使用函數時不會使用索引,如果一定要使用索引只能建立函數索引。
如:
Where條件中對字段增加處理函數將不使用該列的索引 select * from emp where to_char(hire_date,'yyyymmdd')='20080411' (不使用) select * from emp where hire_date = to_char('20080411','yyyymmdd') (使用)
4、當被索引的列進行隱式的類型轉換時不會使用索引。如:select * from t where indexed_column = 5,而indexed_column列建立索引但類型是字符型,這時Oracle會產生 隱式的類型轉換,轉換后的語句類似於select * from t where to_number(indexed_column) = 5,此時不走索引的情況類似於case3。日期轉換也有類似問題,如: select * from t where trunc(date_col) = trunc(sysdate)其中date_col為索引列,這樣寫不會走索引,可改寫成select * from t where date_col >= trunc(sysdate) and date_col < trunc(sysdate+1),此查詢會走索引。 5、並不是所有情況使用索引都會加快查詢速度,full scan table 有時會更快,尤其是當查詢的數據量占整個表的比重較大時,因為full scan table采用的是多塊讀, 當Oracle優化器沒有選擇使用索引時不要立即強制使用,要充分證明使用索引確實查詢更快時再使用強制索引。
6、<>
7、like’�’百分號在前
8、not in ,not exist.