摘要:請把數(shù)據(jù)表想象成一本書,索引就是書的目錄。那么索引過多會導(dǎo)致插入更新操作性能下降。哪些查詢會無法使用索引優(yōu)化中要注意這些情況,調(diào)整以便使用索引模糊查詢在字符串開端使用通配符,會忽略索引。
請把數(shù)據(jù)表想象成一本書, 索引就是書的目錄。
這里只討論寫ORACLE SQL中優(yōu)化時常遇到的索引,一般有以下幾類,
1. normal 順序的btree 索引,字段值可以為空,
2. unique 唯一的順序索引,也就是說書的目錄不能出現(xiàn)重復(fù)項(xiàng),這樣索引建立時,字段是不允許有空值的
3. 組合索引 多個字段放到一起建立的 normal索引,類似于書的目錄是多級的
4. 函數(shù)索引
5. 位圖索引 適合于某列的取值情況較少, 例如性別,只有男女兩個值
更復(fù)雜的索引, 不作討論
索引的優(yōu)點(diǎn)
檢索速度快,根據(jù)目錄去找自己需要的東西, 顯然比整個書翻一遍(全表掃描)要快很多
索引的缺點(diǎn):
1. 需要多帶帶的存儲空間去保存索引, 如果一張表建了很多索引, 那么索引的空間會更大
2. 如果一張表高并發(fā)操作主要是插入、更新。那么索引過多會導(dǎo)致插入更新操作性能下降。
類似書的內(nèi)容總在變,目錄自然也要同時跟著變化。維護(hù)目錄會增加額外的消耗
在書目錄查找的時候, 當(dāng)我們找到需要的章節(jié)時,會記住這些章節(jié)的頁碼, 再翻到相應(yīng)的頁碼去尋找我們需要的內(nèi)容。
這里有兩次查找: 1. 從目錄找頁碼 2. 根據(jù)頁碼在內(nèi)容中查找自己需要的
oracle 也是這樣, 根據(jù)索引篩選可能需要的記錄 rowid(rowid 是oracle每一行記錄的實(shí)際物理地址,類似頁碼,精確到了每一行),利用rowid 讀取行記錄, 逐行讀取記錄的時候再比較這些記錄是否符合其他where條件。最后返回符合條件的行。
注意:一次不可分割的子查詢中中, 不論表建了多少索引,只會使用一條索引。例如
select * from users where userid=3 and username like "json%"。
假設(shè)userid跟username字段都建立了索引,如果同時使用兩條索引,userid返回了等于3的一個rowid(這里是假設(shè),實(shí)際情況一般不知一個,例如用戶登錄記錄表), username 返回json開頭的5個rowid。 通過兩組rowid 我們還是無法得知,哪些rowid同時符合兩個條件。
如何通過索引查找的更快oracle 有自己的分析規(guī)則,還是上面的例子, 利用userid查找起來 更快,一方面因?yàn)樗环祷亓艘粋€rowid, 后續(xù)的查找只需遍歷一個結(jié)果集,判斷這個結(jié)果集是否 like "json%",另一方面like操作更耗時。哪條索引查出來的rowid少自然就更快。
我們可以用索引提示的方式,來指定oracle使用哪條索引,使用這樣的格式 /*+index(表名或表別名 索引名)*/
select /*+index(users users_idx1)*/ * from users where userid=3 and username like "json%"
實(shí)際情況中, 可能更復(fù)雜,例如:
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 都是獨(dú)立的normal索引,而且查詢效率都較高,需要根據(jù)表的實(shí)際情況去選擇。如果 用戶量很大,查詢的時間只是到天,可能使用userid字段的索引更快,如果查詢的時間精確到了秒, 可能時間索引更快
如果需要查看 oracle 使用了哪條索引,查看執(zhí)行計(jì)劃便可,在pl/sql工具中,只需按F5或explain sql
組合索引的情況復(fù)雜一些類似書的目錄有多級目錄一樣, 組合索引是建立在多個字段的, 不同的字段順序不同的組合索引,類似多級目錄,調(diào)換了上下級,就是新的目錄。
基本上書籍都是多級目錄, 一般從我們一級目錄開始查找。
組合索引也遵循這樣的規(guī)則,示例如下:
create index user_idx1 on user_log(userid, username, log_time) // 以下方式,查詢條件中使用了組合索引第一列(前導(dǎo)列)都可以使用 組合索引 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");函數(shù)索引
查找中對字段使用函數(shù)時,將會忽略直接創(chuàng)建于字段上的索引。
select * from users where upper(username) = "JSON"
這樣的查詢, 需要創(chuàng)建函數(shù)索引
create index users_upper_idx on users(upper(username))
理解起來也很簡單, 當(dāng)對字段使用了函數(shù)的時候,查詢已經(jīng)不是字段的值了,原來基于字段值建立的索引,自然失效。
哪些查詢會無法使用索引sql優(yōu)化中要注意這些情況,調(diào)整sql以便使用索引
模糊查詢在字符串開端使用通配符,會忽略索引。如 like "%json" 或 like "%json%"
對非函數(shù)索引的字段, 使用了函數(shù)
對于index索引 不會存儲 null類型,is null 是不會使用該類索引的
索引本身是利用合理的數(shù)據(jù)結(jié)構(gòu),根據(jù)值的比較,來達(dá)到快速檢索的目的,以上列舉的幾種情況,顯然都無法通過比較值來查找到最終結(jié)果
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/17431.html
閱讀 2302·2023-04-25 16:42
閱讀 1204·2021-11-22 14:45
閱讀 2341·2021-10-19 13:10
閱讀 2828·2021-09-29 09:34
閱讀 3412·2021-09-23 11:21
閱讀 2103·2021-08-12 13:25
閱讀 2185·2021-07-30 15:15
閱讀 3496·2019-08-30 15:54