Ordinary hut

          人間一福地,勝似天仙宮
          posts - 61, comments - 50, trackbacks - 0, articles - 1

          oracle的各種索引介紹

          Posted on 2009-08-11 16:51 landor 閱讀(2793) 評(píng)論(0)  編輯  收藏 所屬分類: oracle
          索引:
          最常用的索引包括:B*樹索引、位圖索引、位圖聯(lián)合索引、基于函數(shù)索引、應(yīng)用域索引
          1 B*書索引:實(shí)現(xiàn)快速定位,數(shù)據(jù)庫(kù)會(huì)根據(jù)所索引的列來(lái)建立索引,如果該列是唯一的就將該列進(jìn)行排序,然后建立索引,如果該列不唯一則加入rowid列,使其達(dá)到唯一,然后進(jìn)行排序,借用oracle編程藝術(shù)中的圖:
           
          B*樹索引包括如下幾種:

                  普通索引
                  反向鍵索引:將索引列用reverse函數(shù)反序后建立索引,這是為了避免當(dāng)同時(shí)插入數(shù)據(jù)太多,導(dǎo)致同一個(gè)索引塊忙碌的情況,比如同時(shí)插入1w個(gè)記錄,這1w個(gè)記錄就會(huì)同時(shí)在一個(gè)索引塊里創(chuàng)建索引,導(dǎo)致該塊忙碌,影響性能
                  降序索引:索引默認(rèn)是按照索引列遞增的順序進(jìn)行排序的,如果索引列是遞減的也可以用默認(rèn)的索引,畢竟倒過(guò)來(lái)就是遞減的;但是如果索引列有2個(gè)字段,而當(dāng)我查詢的時(shí)候一個(gè)是asc,一個(gè)是desc,這時(shí)候默認(rèn)索引到不到預(yù)期的效果;但是如果給遞減列用上降序索引,的增列用上默認(rèn)索引的話,那么性能會(huì)大幅提高;
                關(guān)于聚簇因子:oracle有一個(gè)表叫user_indexes,在這里可以查詢所有的索引,比如執(zhí)行查詢
               
                select a.index_name,b.num_rows,b.blocks,a.clustering_factor from user_indexes a, user_tables b
                where index_name in ('xx1','xx2'and a.table_name = b.table_name;
                其中clustering_factor:聚簇因子    index_name索引名   num_rows:行數(shù)   blocks:數(shù)據(jù)塊
                如果clustering_factor非常接近blocks,說(shuō)明數(shù)據(jù)非常有序,連續(xù)的數(shù)據(jù)可能在一個(gè)塊中,這樣進(jìn)行區(qū)間段等大數(shù)據(jù)查詢的時(shí)候,性能越高
                如果clustering_factor非常接近num_rows,說(shuō)明數(shù)據(jù)非常隨即。索引條目指向的數(shù)據(jù)不一定在一個(gè)快中,進(jìn)行區(qū)間等查詢的時(shí)候,性能很差

                B*樹索引應(yīng)用場(chǎng)合:1 僅僅返回少數(shù)數(shù)據(jù),數(shù)據(jù)重復(fù)度低;2 直接用索引能完成,沒(méi)有涉及到表(比如select count(x) where x='xx',這種語(yǔ)句直接檢索索引,根本接觸不到表本身,速度顯然很快)

          2 位圖索引:對(duì)于頻繁更新的表,不適合建立位圖索引;位圖索引會(huì)記錄該列的數(shù)據(jù)1存放在1,3,4,7...行,數(shù)據(jù)2存放在2,5,6...行,數(shù)據(jù)null存放在8,9...行等等,會(huì)把所有數(shù)據(jù)及其位置都記錄下來(lái);
              所以,數(shù)據(jù)的重復(fù)度越高,越適合位圖索引;如何衡量呢,就是不同相數(shù)據(jù)的個(gè)數(shù)除以總行數(shù)越接近零越好;偽代碼:count(distinct(col))/count(*)越接近零,越適合做位圖索引;
              以上數(shù)據(jù)不應(yīng)該建立B*樹索引,因?yàn)锽*樹是樹形結(jié)構(gòu),而重復(fù)度高的數(shù)據(jù),會(huì)根據(jù)一個(gè)值檢索到大量的數(shù)據(jù)。這違背了b*樹索引的原則。

              如果進(jìn)行查詢select count(*) from Table1 where col1='x' or col1='y',這個(gè)就會(huì)用到位圖索引,只是將2個(gè)合并,都不會(huì)去查詢表,在索引中直接返回正確結(jié)果
              如果進(jìn)行查詢select * from table1 wwhere col1='x' or col1='y',這個(gè)會(huì)用到位圖索引,oracle會(huì)到位圖索引去找到所有x和y的索引,然后找到相應(yīng)的rowid,然后根據(jù)rowid快速返回結(jié)果集

              對(duì)于頻繁更新的表,為什么不適合用位圖索引:一個(gè)位圖索引中維護(hù)了一個(gè)數(shù)據(jù)和多個(gè)行的位置,如果一個(gè)會(huì)話修改了該列某一行的指定數(shù)據(jù),比如xx1,那么該位圖索引所維護(hù)的xx1數(shù)據(jù)的所有行都會(huì)被鎖定;oracle是無(wú)法鎖定一個(gè)位圖索引中的某一個(gè)行的。這樣就會(huì)出現(xiàn)如下問(wèn)題:
              如果該數(shù)據(jù)有100行,那么更新一行的時(shí)候,100行數(shù)據(jù)均被鎖定,導(dǎo)致其他會(huì)話只能等待期釋放之后才能操作;如果頻繁出現(xiàn)這種情況的話,性能會(huì)嚴(yán)重下降。

          3 位圖聯(lián)結(jié)索引:這是oracle9i所引入的一個(gè)索引;對(duì)于關(guān)聯(lián)表建立位圖索引,比如有一個(gè)部門表和員工表,員工表中存放了部門表的主鍵,此時(shí)想根據(jù)部門的name來(lái)查詢所有的員工,這是如果建立和位圖聯(lián)結(jié)索引,聚會(huì)很快得到結(jié)果集;

          4 基于函數(shù)的索引(待續(xù))

          關(guān)于索引常見的問(wèn)題:
          1 視圖能建立索引嗎:視圖引用的是基本表,只需要對(duì)基本表建立索引,就相當(dāng)于在視圖中建立索引;
          2 Null和索引的協(xié)作:
              -- B*樹索引不能建立在都可以為null的列上,因?yàn)锽*書索引會(huì)過(guò)濾掉null,也就是說(shuō),當(dāng)進(jìn)行查詢的時(shí)候:
              比如在col1和col2上建立了索引,col1和col2都可以為空,查詢select * from table1 where col1 is null 這個(gè)語(yǔ)句不會(huì)使用索引,因?yàn)槿绻褂盟饕脑挘赡軙?huì)丟失數(shù)據(jù)(那些null的數(shù)據(jù)會(huì)丟失);因?yàn)樗饕裏o(wú)法建立在都可以為null的列上,oracle優(yōu)化器會(huì)選擇不使用索引,而是全表掃描;
          3 外鍵是否可以建立索引:在以下情況中,最好在外鍵上建索引
              a 如果經(jīng)常進(jìn)行聯(lián)機(jī)刪除或者修改父表主鍵的情況,建議在子表外鍵上建立索引。如果不建立索引的話,有上述操作時(shí),oracle會(huì)把整個(gè)子表全部鎖死,這也是oracle出現(xiàn)死鎖的情況,嚴(yán)重影響系統(tǒng)性能;
              b 從父表查詢子表信息的時(shí)候,比如根據(jù)deptName查詢?cè)摬块T下所有員工信息的時(shí)候,建議在子表外鍵上建立索引,或者建立位圖聯(lián)結(jié)索引,否則如果頻繁進(jìn)行上述查詢的話,速度會(huì)很慢,因?yàn)槊看味紝?duì)員工表進(jìn)行了全表掃描。

          4 索引為何失效
              a 關(guān)于B*樹索引,如果是a、b兩列建立索引,如果a、b兩列都允許為空的話,由于在全是null的數(shù)據(jù)上不會(huì)建立索引,所以為了避免查詢數(shù)據(jù)不準(zhǔn)確,優(yōu)化器會(huì)放棄使用索引,而是使用全表掃描;
              b 關(guān)于B*樹索引,如果是a、b兩列建立索引,如果這樣select * from table1 where b =5;此時(shí)如果a列的數(shù)據(jù)重復(fù)率不高的話,如果用索引的話,會(huì)去檢索每條索引的數(shù)據(jù),這樣優(yōu)化器更傾向于用全表掃描;如果a數(shù)據(jù)重復(fù)度很高,優(yōu)化器會(huì)用一種跳躍式掃描方式,此時(shí)會(huì)用上索引;
              c 如果用到了函數(shù),比如select * from table1 where f(a) = xx;此時(shí)不會(huì)用到索引,因?yàn)樗饕墙⒃赼上的,而不是建立在f(a)上的;
              d 如果a列是字符類型,但是我們執(zhí)行了select * from table1 where a = 5;此時(shí)其實(shí)是隱式的應(yīng)用了to_number(a)=5;索引是建立在a上,而不是建立在函數(shù)上的;
              e 有些時(shí)候oracle的優(yōu)化器會(huì)智能的判斷使用索引后是否會(huì)提高效率,如果不會(huì)提高效率那么優(yōu)化器會(huì)自動(dòng)放棄索引,而執(zhí)行full table;此時(shí)請(qǐng)檢查索引的合理性;
              oracle編程藝術(shù)上說(shuō):歸根結(jié)底,原因通常就是
                  “不能使用索引,使用索引會(huì)返回不正確的結(jié)果”
                  “不應(yīng)該使用索引,使用了,性能會(huì)變得很糟糕”

          另外:如果是兩個(gè)列建立索引,那么哪個(gè)放前面,哪個(gè)放后面呢:
              這個(gè)要視情況而定,如果只有如下查詢select * from table1 where a= :x and b= :y,那么哪個(gè)在前面都無(wú)所謂;
              如果還有這種方式:select * from table1 where b = :y ,那么需要b列在前面;

              oracle編程藝術(shù)中還就索引壓縮做出對(duì)比,這里不記錄了。以上都是個(gè)人理解記錄,都是為了方便自己。

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 扶沟县| 大丰市| 安图县| 天峨县| 桃园县| 康马县| 达拉特旗| 高雄县| 建始县| 绥芬河市| 横山县| 建瓯市| 拉孜县| 启东市| 广州市| 博湖县| 蓝田县| 托克逊县| 寿阳县| 盐城市| 海盐县| 汝阳县| 金溪县| 全椒县| 河东区| 布尔津县| 肥乡县| 南木林县| 时尚| 康马县| 德化县| 中超| 沾益县| 许昌市| 东乌珠穆沁旗| 行唐县| 攀枝花市| 宁城县| 桂东县| 雅安市| 兴海县|