淺談Oracle索引

最近在作有關查詢數據庫的工做,因爲一個表的數據量過大,致使程序進程卡死狀況出現,SQL優化迫在眉睫,索引閃亮登場!sql

Oracle中查詢走索引的狀況:數據庫

一、對返回的行無任何限定條件,即沒有where子句。服務器

二、未對數據表與任何索引主列相對應的行限定條件。函數

例如:在id-name-time列建立了三列複合索引,那麼僅對name列限定條件不能使用這個索引,由於name不是索引的主列。性能

三、對索引的主列有限定條件,可是在條件表達式裏使用如下表達式則會使索引失效,形成權標掃描:大數據

(1)where子句中對字段進行函數、表達式操做,這將致使引擎放棄使用索引而進行全表掃描。優化

(2)查詢字段is null時索引失效,引發全表查詢。搜索引擎

解決辦法:SQL語法中使用null會有不少麻煩,最好索引列時not null的;對於is null,能夠創建組合索引, nvl(字段,0),對錶和索引analyse後,is null查詢時能夠從新啓用索引查找,可是效率還不是值得確定;is not null時永遠不會使用索引。通常數據量大的表不要用is null查詢。spa

(3) 查詢條件中使用了不等於操做符(<>、!=)會限制索引、引發全表掃描日誌

解決方法:經過把不等於操做符改爲or,可使用索引,避免全表掃描。
例如,把column<>10,改爲column<10 or column>10,就可使用索引了。

(4)對索引的主列有限定條件,可是條件使用like操做以及值以‘%’開始或者值是一個賦值變量。

例如:where city like '%大連%'。

select * from citys where name like '%大連' (不使用索引)
select * from citys where name like '大連%' (使用索引) 。

解決辦法:首先儘可能避免模糊查詢,若是必須使用,不採用全模糊查詢,也應儘可能採用右模糊查詢, 即like ‘…%’,是會使用索引的;左模糊like ‘%...’沒法直接使用索引,但能夠利用reverse + function index 的形式,變化成 like ‘…%’;

全模糊查詢是沒法優化的,必定要使用的話建議使用搜索引擎。

四、 or語句使用不當會引發全表掃描

緣由:where子句中比較的兩個條件,一個有索引,一個沒索引,使用or則會引發全表掃描。
例如:where A=:1 or B=:2,A上有索引,B上沒索引,則比較B=:2時會從新開始全表掃描

五、組合索引

排序時應按照組合索引中各列的順序進行排序,即便索引中只有一個列是要排序的,不然排序性能會比較差。

例如:

create index skip1 on emp5(job,empno,date);
select job,empno from emp5 where job=’manager’ and empno=’10’ order by job,empno,date desc;

實際上只是查詢出符合 job=’manager’ and empno=’10’  條件的記錄並按date降序排序,但寫成order by date desc性能較差。

六、 Update語句,若是隻更改一、2個字段,不要Update所有字段,不然頻繁調用會引發明顯的性能消耗,同時帶來大量日誌。

七、 對於多張大數據量的表JOIN,要先分頁再JOIN,不然邏輯讀會很高,性能不好。

八、 select count(*) from table;
這樣不帶任何條件的count會引發全表掃描,而且沒有任何業務意義,是必定要杜絕的。

九、 sql的where條件要綁定變量,好比where column= 1,不要寫成where column=‘aaa’,這樣會致使每次執行時都會從新分析,浪費CPU和內存資源。

十、 不要使用in操做符,這樣數據庫會進行全表掃描。

十一、 not in 使用not in也不會走索引

推薦方案:用not exists或者(外聯結+判斷爲空)來代替

十二、 > 及 < 操做符(大於或小於操做符)

大於或小於操做符通常狀況下是不用調整的,由於它有索引就會採用索引查找。
但有的狀況下能夠對它進行優化,如一個表有100萬記錄,一個數值型字段 A,30萬記錄的A=0,30萬記錄的A=1,39萬記錄的A=2,1萬記錄的A=3。
那麼執行A>2與A>=3的效果就有很大的區別了,由於A>2時ORACLE會先找出爲2的記錄索引再進行比較,而A>=3時ORACLE則直接找到=3的記錄索引。

1三、 UNION操做符

UNION在進行表連接後會篩選掉重複的記錄,因此在表連接後會對所產生的結果集進行排序運算,刪除重複的記錄再返回結果。
實際大部分應用中是不會產生重複的記錄,最多見的是過程表與歷史表UNION。如:
select * from gc_dfys
union
select * from ls_jg_dfys
這個SQL在運行時先取出兩個表的結果,再用排序空間進行排序刪除重複的記錄,最後返回結果集,若是表數據量大的話可能會致使用磁盤進行排序。
推薦方案:採用UNION ALL操做符替代UNION,由於UNION ALL操做只是簡單的將兩個結果合併後就返回。

1四、 WHERE後面的條件順序影響

Select * from zl_yhjbqk where dy_dj = '1K如下' and xh_bz=1
Select * from zl_yhjbqk where xh_bz=1 and dy_dj = '1K如下'

以上兩個SQL中dy_dj及xh_bz兩個字段都沒進行索引,因此執行的時候都是全表掃描,
第一條SQL的dy_dj = '1KV如下'條件在記錄集內比率爲99%,而xh_bz=1的比率只爲0.5%,在進行第一條SQL的時候99%條記錄都進行dy_dj及xh_bz的比較。
而在進行第二條SQL的時候 0.5%條記錄都進行dy_dj及xh_bz的比較,以此能夠得出第二條SQL的CPU佔用率明顯比第一條低。

1五、查詢表順序的影響

在FROM後面的表中的列表順序會對SQL執行性能影響,在沒有索引及ORACLE沒有對錶進行統計分析的狀況下ORACLE會按表出現的順序進行連接,
由此由於表的順序不對會產生十分耗服務器資源的數據交叉。(注:若是對錶進行了統計分析,ORACLE會自動先進小表的連接,再進行大表的連接)

錶鏈接時,數據量大的爲主表效率更高。

相關文章
相關標籤/搜索