數據庫索引優化 oracle

請把數據表想象成一本書, 索引就是書的目錄。
這裏只討論寫ORACLE SQL中優化時常遇到的索引,通常有如下幾類,
1. normal 順序的btree 索引,字段值能夠爲空,
2. unique 惟一的順序索引,也就是說書的目錄不能出現重複項,這樣索引創建時,字段是不容許有空值的
3. 組合索引 多個字段放到一塊兒創建的 normal索引,相似於書的目錄是多級的
4. 函數索引
5. 位圖索引 適合於某列的取值狀況較少, 例如性別,只有男女兩個值
更復雜的索引, 不做討論sql

索引的優缺點:

索引的優勢
檢索速度快,根據目錄去找本身須要的東西, 顯然比整個書翻一遍(全表掃描)要快不少
索引的缺點:
1. 須要單獨的存儲空間去保存索引, 若是一張表建了不少索引, 那麼索引的空間會更大
2. 若是一張表高併發操做主要是插入、更新。那麼索引過多會致使插入更新操做性能降低。
相似書的內容總在變,目錄天然也要同時跟着變化。維護目錄會增長額外的消耗json

oracle 是如何經過索引找到記錄的?

在書目錄查找的時候, 當咱們找到須要的章節時,會記住這些章節的頁碼, 再翻到相應的頁碼去尋找咱們須要的內容。
這裏有兩次查找: 1. 從目錄找頁碼 2. 根據頁碼在內容中查找本身須要的
oracle 也是這樣, 根據索引篩選可能須要的記錄 rowid(rowid 是oracle每一行記錄的實際物理地址,相似頁碼,精確到了每一行),利用rowid 讀取行記錄, 逐行讀取記錄的時候再比較這些記錄是否符合其餘where條件。最後返回符合條件的行。
注意:一次不可分割的子查詢中中, 不論表建了多少索引,只會使用一條索引。例如數據結構

select * from users where userid=3 and username like 'json%'。

假設userid跟username字段都創建了索引,若是同時使用兩條索引,userid返回了等於3的一個rowid(這裏是假設,實際狀況通常不知一個,例如用戶登陸記錄表), username 返回json開頭的5個rowid。 經過兩組rowid 咱們仍是沒法得知,哪些rowid同時符合兩個條件。併發

如何經過索引查找的更快

oracle 有本身的分析規則,仍是上面的例子, 利用userid查找起來 更快,一方面由於它只返回了一個rowid, 後續的查找只需遍歷一個結果集,判斷這個結果集是否 like 'json%',另外一方面like操做更耗時。哪條索引查出來的rowid少天然就更快。
咱們能夠用索引提示的方式,來指定oracle使用哪條索引,使用這樣的格式 /*+index(表名或表別名 索引名)*/oracle

select /*+index(users users_idx1)*/ * from users where userid=3 and username like 'json%'

實際狀況中, 可能更復雜,例如:函數

select * from users where userid=3 and login_time=to_date('yyyy-mm-dd hh24:mi:ss', '2014-02-14 03:00:00')

這裏可能userid 跟 login_time 都是獨立的normal索引,並且查詢效率都較高,須要根據表的實際狀況去選擇。若是 用戶量很大,查詢的時間只是到天,可能使用userid字段的索引更快,若是查詢的時間精確到了秒, 可能時間索引更快高併發

若是須要查看 oracle 使用了哪條索引,查看執行計劃即可,在pl/sql工具中,只需按F5或explain sql工具

組合索引的狀況複雜一些

相似書的目錄有多級目錄同樣, 組合索引是創建在多個字段的, 不一樣的字段順序不一樣的組合索引,相似多級目錄,調換了上下級,就是新的目錄。
基本上書籍都是多級目錄, 通常從咱們一級目錄開始查找。
組合索引也遵循這樣的規則,示例以下:性能

create index user_idx1 on user_log(userid, username, log_time)
// 如下方式,查詢條件中使用了組合索引第一列(前導列)均可以使用 組合索引
select * from user_log where userid=3 and  username like 'json%' and log_time=to_date('yyyy-mm-dd hh24', '2014-02-14 03');
select * from user_log where userid=3 and log_time=to_date('yyyy-mm-dd hh24', '2014-02-14 03');
select * from user_log where userid=3;
// 跳過 第一列的狀況, 將再也不使用使用組合索引(oracle 9i以上版本會使用跳躍掃描)
selec * from user_log where log_time=to_date('yyyy-mm-dd hh24', '2014-02-14 03');

函數索引

查找中對字段使用函數時,將會忽略直接建立於字段上的索引。優化

select * from users where upper(username) = 'JSON'

這樣的查詢, 須要建立函數索引

create index users_upper_idx on users(upper(username))

理解起來也很簡單, 當對字段使用了函數的時候,查詢已經不是字段的值了,原來基於字段值創建的索引,天然失效。

哪些查詢會沒法使用索引

sql優化中要注意這些狀況,調整sql以便使用索引
模糊查詢在字符串開端使用通配符,會忽略索引。如 like '%json'like '%json%' 對非函數索引的字段, 使用了函數 對於index索引 不會存儲 null類型,is null 是不會使用該類索引的 索引自己是利用合理的數據結構,根據值的比較,來達到快速檢索的目的,以上列舉的幾種狀況,顯然都沒法經過比較值來查找到最終結果

相關文章
相關標籤/搜索