Oracle中如何選擇合適的索引類型


雖然說,在表中是否創建索引,不會影響到Oracle數據庫的使用,也不會影響數據庫語句的使用。這就好像即使字典沒有目錄的話,用戶仍然可以使用它一樣。可是,若字典沒有目錄,那麼可想而知,用戶要查某個條目的話,其不得不翻遍整本字典。數據庫也是如此。若沒有建立相關索引的話,則數據庫在查詢記錄的時候,不得不去查詢整個表。當表中的記錄比較多的時候,其查詢效率就會很低。所以,合適的索引,是提高數據庫運行效率的一個很好的工具。

不過,並不是說表上的索引越多越好。過之而不及。故在數據庫設計過程中,還是需要爲表選擇一些合適的索引。寧缺勿濫,這是建立索引時的一個遵循標準。在理論上,雖然一個表可以設置無限的索引。但是,數據庫管理員需要知道,表中的索引越多,維護索引所需要的開銷也就越大。每當數據表中記錄有增加、刪除、更新變化的時候,數據庫系統都需要對所有索引進行更新。故數據庫表中的索引絕對不是多多益善。具體來說,在索引建立上,筆者對大家有如下建議。

建議一:在基數小的字段上要善於使用位圖索引。

基數是位圖索引中的一個基本的定義,它是指數據庫表中某個字段內容中不重複的數值。如在員工信息表中的性別字段,一般就只有男跟女兩個值,所以,其基數爲2;婚姻狀況字段的話,則其只有已婚、未婚、離婚三種狀態,其基數就爲3;民族一覽內也是隻有有限的幾個值。

對於要查詢基數小的字段,如現在用戶想查找所有婚姻狀況爲“已婚”的“女性”時,利用位圖索引可以提高查詢的效率。這主要是因爲標準索引是通過在索引中保存排序過的索引列以及對應的ROWID來實現的。若我們在基數小的列上建立標準索引的話,則其會返回大量的記錄。

而當我們在創建位圖索引的時候,在Oracle會對整個表進行掃描,並且會爲索引列的每個取值建立一個位圖。若內容相同,則在位圖上會以一個相同的數字表示。此時,若這個字段的基數比較小的話,則若需要實現對整個字段的查詢的話,效率就會非常的高。因爲此時,數據庫只要位圖中數字相同的內容找出來即可。

除了在數據表某列基數比較小的情況下,採用位圖索引外,我們往往在一些特殊的情況下,也會建議採用位圖索引。最常見的情況是,在Where限制條件中,若我們多次採用AND或者OR條件時,也建議採用位圖索引。因爲當一個查詢飲用了一些部署了位圖索引的列的時候,這些位圖可以很方便的與AND或者Or 運算符操作結合以快速的找出用戶所需要的記錄。

但是,這裏要注意,不是在條件語句中包含運算符的時候,採用位圖索引都能夠提供比較高的效率。一般來說,只有AND 或者OR運算符的時候,位圖索引纔會比較具有優勢。若此時用戶採用大於號或者不等於號作爲條件語句中的限制條件的時候,則往往採用標準索引具有更大的優勢。

所以,筆者在數據庫設置中,一般只有在三種情況下才採用位圖索引。一是列的基數比較小,而有可能需要根據這些字段的內容查找相關的記錄;二是在條件語句中,用到了AND或者OR運算符的時候。除了這兩種情況外,最好能夠採用其他適合的索引。第三種情況是,需要用到NULL作爲查詢的限制條件。因爲標準查詢一般情況下,會忽略所有的NULL值列。也就是說,若需要查詢“所有沒有身份證號碼”的員工的信息的時候,標準索引並不能夠起到加速查詢速度的作用。此時,就需要採用位圖索引。因爲位圖索引會記錄相關的NULL值列信息。

建議二:創建索引的一些限制條件。

並不說,表或者列建立的索引越多越好。相反,索引建的越多,有時會反而會影響數據庫運行的整體性能。所以,在建立索引的時候,仍然會有一些限制條件。

一是不要對一些記錄內容比較少的表建立索引。在一個應用系統設計的時候,如設計一個ERP系統的數據庫,其雖然有幾千張表。但是,並不是每張表都有大量記錄的。相反,其中有近一半左右的數據表,可能其存儲的數據不會超過百條。如員工登陸帳戶密碼錶、企業部門信息表等等。對於這些記錄內容比較少的表,我們建立最好不要爲其建立索引。無論是表上的,還是字段上,都不要建立索引。

二是若表中的內容比較大,但是,這個表基本上不怎麼查詢的時候,則只需要在表上建立索引即可;而不需要在字段上建立索引。如現在在ERP系統中,有一張表是“AD_Table”。其存儲的是這個數據庫中相關表的信息。這張表只有在數據庫設計的時候纔會用到。故這張表中的記錄雖然比較多,但是由於用戶用的比較少,所以,一般沒有必要爲這張表建立列級別上的索引。而直接用表索引來代替。

三是在一些NULL字段上,要根據實際情況來判斷是否要建立索引。如現在有一張人事檔案的表格,其上面有兩個字段,分別爲“身份證號碼”與“地區”。有時會爲了某個原因,企業需要所有員工都在系統中登記他們的身份證號碼,以方便他們辦工資卡、社會保險等等。所以人事管理可能需要經常的查詢系統,看看有沒有沒有身份證號碼的員工信息。此時,就需要利用條件“IS NULL”來查詢我們所需要的記錄。故爲了提高查詢效率,若某個記錄可能爲空,並且經常需要以NULL爲條件進行查詢的時候,則最好給這個字段添加一個索引,並且最好建立位圖索引。相反,若雖然可能會以NULL這個條件作爲查詢的限制語句,但是,用的不是很多的時候,則就沒有必要爲其建立索引。

建議三:多表連接查詢的索引設計。

如現在有一個人事管理系統。人事經理想知道員工的社保繳納情況。他需要知道員工的姓名、職務、戶籍性質(農民戶口跟居民戶口費用不一樣)、繳納的情況等等。但是,這些信息包含在不同的表中。因爲爲了提高數據庫的性能,在表中存儲的可能只是某些序號,而不是具體的內容。如在社保表中,存儲的是員工對應的編號,而不是員工的名字。所以,要得到這份報表的話,就可能需要關聯員工基本信息表、公司組織結構表等表格,才能夠查詢到用戶所需要的內容。

爲此,就需要利用Join語句,把這些表格關聯起來。爲了提高數據庫的查詢效率,這些用來關聯的字段,最好能夠建立索引。這可以顯著的提高查詢的速度。

建議四:在表的更新速度與查詢速度之間尋求一個平衡點。

衆所周知,索引本身並不影響數據庫的使用,其主要是爲了提高數據庫的查詢效率。但是,由於當數據庫的表中的數據更新的時候,包括記錄的增加、刪除、更改等等,都會對雖有的索引進行更新。

很明顯,索引雖然可以提高查詢速度。但是,也會對一些表的更新操作產生不良的影響。當在表中建立的索引越多,這個不利影響也會越大。故數據庫管理員在設置索引的時候,還需要注意,在這兩個之間需要一個均衡點。

按照一般的理論來說,當某個表多數用來查詢、更新相對來說比較上的話,則要多多采用索引。相反,當某個表記錄更新居主導,查詢相對來說比較少的話,則不要建立太多的索引,避免對更新的速度差生不利影響。

在實際工作中,若某個表頻繁的被視圖所調用的話,則最好就好設置比較多的索引。在選擇數據庫索引時大家可以參考上文給出的四點建議,相信掌握了上文中的四點建議,大家一定能選擇一款合適的索引類型。

轉載自:http://database.51cto.com/art/201103/250674.htm#585532-tqq-1-96480-a3e9a686e55f3c274cc3657df120d3bf



---------------------------------------------------------------------------------------------------------------------

補充:

索引的特點
    1.索引可以加快數據庫的檢索速度 
    2.索引降低了數據庫插入、修改、刪除等維護任務的速度 
    3.索引創建在表上,不能創建在視圖上 
    4.索引既可以直接創建,也可以間接創建 
    5.可以在優化隱藏中,使用索引 
    6.使用查詢處理器執行SQL語句,在一個表上,一次只能使用一個索引 
    7.其他

索引的優點
    1.創建唯一性索引,保證數據庫表中每一行數據的唯一性
    2.大大加快數據的檢索速度,這也是創建索引的最主要的原因
    3.加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。
    4.在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。
    5.通過使用索引,可以在查詢的過程中使用優化隱藏器,提高系統的性能。

索引的缺點
    1.創建索引和維護索引要耗費時間,這種時間隨着數據量的增加而增加
    2.索引需要佔物理空間,除了數據表佔數據空間之外,每一個索引還要佔一定的物理空間,如果要建立聚簇索引,那麼需要的空間就會更大
    3.當對錶中的數據進行增加、刪除和修改的時候,索引也要動態的維護,降低了數據的維護速度

索引分類
    1.直接創建索引和間接創建索引
    直接創建索引: CREATE INDEX mycolumn_index ON mytable (myclumn)
    間接創建索引:定義主鍵約束或者唯一性鍵約束,可以間接創建索引
    2.普通索引和唯一性索引
    普通索引:CREATE INDEX mycolumn_index ON mytable (myclumn)
    唯一性索引:保證在索引列中的全部數據是唯一的,對聚簇索引和非聚簇索引都可以使用
    CREATE UNIQUE COUSTERED INDEX myclumn_cindex ON mytable(mycolumn)
    3.單個索引和複合索引
    單個索引:即非複合索引
    複合索引:又叫組合索引,在索引建立語句中同時包含多個字段名,最多16個字段
    CREATE INDEX name_index ON username(firstname,lastname)
    4.聚簇索引和非聚簇索引(聚集索引,羣集索引)
   聚簇索引:物理索引,與基表的物理順序相同,數據值的順序總是按照順序排列
    CREATE CLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn) WITH
    ALLOW_DUP_ROW(允許有重複記錄的聚簇索引)
   非聚簇索引:CREATE UNCLUSTERED INDEX mycolumn_cindex ON mytable(mycolumn)

索引的使用
   1.當字段數據更新頻率較低,查詢使用頻率較高並且存在大量重複值是建議使用聚簇索引
    2.經常同時存取多列,且每列都含有重複值可考慮建立組合索引
    3.複合索引的前導列一定好控制好,否則無法起到索引的效果。如果查詢時前導列不在查詢條件中則該複合索引不會被使用。前導列一定是使用最頻繁的列
    4.多表操作在被實際執行前,查詢優化器會根據連接條件,列出幾組可能的連接方案並從中找出系統開銷最小的最佳方案。連接條件要充份考慮帶有索引的表、行數多的表;內外表的選擇可由公式:外層表中的匹配行數*內層表中每一次查找的次數確定,乘積最小爲最佳方案
    5.where子句中對列的任何操作結果都是在sql運行時逐列計算得到的,因此它不得不進行表搜索,而沒有使用該列上面的索引;如果這些結果在查詢編譯時就能得到,那麼就可以被sql優化器優化,使用索引,避免表搜索(例:select * from record where substring(card_no,1,4)=’5378’ 
&& select * from record where card_no like ’5378%’)任何對列的操作都將導致表掃描,它包括數據庫函數、計算表達式等等,查詢時要儘可能將操作移至等號右邊
    6.where條件中的’in’在邏輯上相當於’or’,所以語法分析器會將in ('0','1')轉化爲column='0' or column='1'來執行。我們期望它會根據每個or子句分別查找,再將結果相加,這樣可以利用column上的索引;但實際上它卻採用了"or策略",即先取出滿足每個or子句的行,存入臨時數據庫的工作表中,再建立唯一索引以去掉重複行,最後從這個臨時表中計算結果。因此,實際過程沒有利用column上索引,並且完成時間還要受tempdb數據庫性能的影響。in、or子句常會使用工作表,使索引失效;如果不產生大量重複值,可以考慮把子句拆開;拆開的子句中應該包含索引
    7.要善於使用存儲過程,它使sql變得更加靈活和高效

------------------------------------------------------------------------------------------------------------------------

聚簇索引與非聚簇索引的區別   

原文連接:http://blog.csdn.net/gufachongyang02/article/details/40083561

    通常情況下,建立索引是加快查詢速度的有效手段。但索引不是萬能的,靠索引並不能實現對所有數據的快速存取。事實上,如果索引策略和數據檢索需求嚴重不符的話,建立索引反而會降低查詢性能。因此在實際使用當中,應該充分考慮到索引的開銷,包括磁盤空間的開銷及處理開銷(如資源競爭和加鎖)。例如,如果數據頻繁的更新或刪加,就不宜建立索引。
    本文簡要討論一下聚簇索引的特點及其與非聚簇索引的區別。
建立索引:
在SQL語言中,建立聚簇索引使用CREATE INDEX語句,格式爲:CREATE CLUSTER INDEX index_name ON table_name(column_name1,column_name2,...);
存儲特點:
聚集索引。表數據按照索引的順序來存儲的,也就是說索引項的順序與表中記錄的物理順序一致。對於聚集索引,葉子結點即存儲了真實的數據行,不再有另外單獨的數據頁。 在一張表上最多隻能創建一個聚集索引,因爲真實數據的物理順序只能有一種。
非聚集索引。表數據存儲順序與索引順序無關。對於非聚集索引,葉結點包含索引字段值及指向數據頁數據行的邏輯指針,其行數量與數據錶行數據量一致。
    總結一下:聚集索引是一種稀疏索引,數據頁上一級的索引頁存儲的是頁指針,而不是行指針。而對於非聚集索引,則是密集索引,在數據頁的上一級索引頁它爲每一個數據行存儲一條索引記錄。
更新表數據
1、向表中插入新數據行
    如果一張表沒有聚集索引,那麼它被稱爲“堆集”(Heap)。這樣的表中的數據行沒有特定的順序,所有的新行將被添加到表的末尾位置。而建立了聚簇索引的數據表則不同:最簡單的情況下,插入操作根據索引找到對應的數據頁,然後通過挪動已有的記錄爲新數據騰出空間,最後插入數據。如果數據頁已滿,則需要拆分數據頁,調整索引指針(且如果表還有非聚集索引,還需要更新這些索引指向新的數據頁)。而類似於自增列爲聚集索引的,數據庫系統可能並不拆分數據頁,而只是簡單的新添數據頁。
2、從表中刪除數據行
    對刪除數據行來說:刪除行將導致其下方的數據行向上移動以填充刪除記錄造成的空白。如果刪除的行是該數據頁中的最後一行,那麼該數據頁將被回收,相應的索引頁中的記錄將被刪除。對於數據的刪除操作,可能導致索引頁中僅有一條記錄,這時,該記錄可能會被移至鄰近的索引頁中,原索引頁將被回收,即所謂的“索引合併”。

什麼是聚集索引??

漢語字典的正文本身就是一個聚集索引。比如,我們要查“安”字,就會很自然地翻開字典的前幾頁,因爲“安”的拼音是“an”,而按照拼音排序漢字的字典是以英文字母“a”開頭並以“z”結尾的,那麼“安”字就自然地排在字典的前部。如果您翻完了所有以“a”開頭的部分仍然找不到這個字,那麼就說明您的字典中沒有這個字;同樣的,如果查“張”字,那您也會將您的字典翻到最後部分,因爲“張”的拼音是“zhang”。也就是說,字典的正文部分本身就是一個目錄,您不需要再去查其他目錄來找到您需要找的內容。正文內容本身就是一種按照一定規則排列的目錄稱爲“聚集索引”。每個表只能有一個聚集索引,因爲目錄只能按照一種方法進行排序。
什麼是非聚集索引??

 如果您認識某個字,您可以快速地從自動中查到這個字。但您也可能會遇到您不認識的字,不知道它的發音,這時候,您就不能按照剛纔的方法找到您要查的字,而需要去根據“偏旁部首”查到您要找的字,然後根據這個字後的頁碼直接翻到某頁來找到您要找的字。但您結合“部首目錄”和“檢字表”而查到的字的排序並不是真正的正文的排序方法,比如您查“張”字,我們可以看到在查部首之後的檢字表中“張”的頁碼是672頁,檢字表中“張”的上面是“馳”字,但頁碼卻是63頁,“張”的下面是“弩”字,頁面是390頁。很顯然,這些字並不是真正的分別位於“張”字的上下方,現在您看到的連續的“馳、張、弩”三字實際上就是他們在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我們可以通過這種方式來找到您所需要的字,但它需要兩個過程,先找到目錄中的結果,然後再翻到您所需要的頁碼。我們把這種目錄純粹是目錄,正文純粹是正文的排序方式稱爲“非聚集索引”。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章