SQL索引

什麼是索引

索引是建立在表的一列或多個列上的輔助對象, 目的是加快訪問表中的數據。

oracle存儲索引的數據結構是B樹,位圖索引(Bitmap索引)也是如此,只不過是葉子節點不同B樹索引。

Bitmap索引:索引由根節點,分支節點和葉子節點組成,上級索引塊包含下級索引快的索引數據,葉節點包含索引數據和確定行實際位置的rowid.

oracle中最常用的索引就倆種:B樹索引和位圖索引。

B樹索引在oracle中是一個通用的索引,在創建索引時他就是默認的類型,最多可以包含32列。

一般情況下,大多數用戶都只創建TYPE爲NORMAL的B樹索引,所以對於較低基數的列我們都是不創建索引的,

因爲B-樹索引對查詢速度提升不一定會有改善,甚至會增加INSERT,UPDATE,DELETE 命令所消耗的時間。

位圖索引爲oracle每一個鍵創建一個位圖,然後把與鍵值所關聯的ROWID保存爲位圖,最多可以包含30列。 

位圖索引在加載表(插入操作)時,通常要比B樹索引做得好。通常,位圖索引要比一個低基數(很少不同值)上的B樹索引要快3~4倍。

但如果新增的值佔插入行的70%以上時,B樹索引通常會更快一些。當每條記錄都增加一個新值時,B樹索引要比位圖索引快3倍。

建議

建議不要在一些聯機事務處理(OLTP)應用程序中使用位圖索引。B樹索引的索引值包含ROWID,這樣oracle就可以在行級別上鎖定索引。

位圖索引被存儲爲壓縮的索引值,其中包含了一個範圍的ROWID,因此ROWID必須對一個給定值鎖定所有範圍內的ROWID。

這種鎖定可能會使某些DML語句中造成死鎖。SELECT語句不會受到這種鎖定問題的影響。 

位圖索引有很多限制

1 基於規則的優化器不會考慮位圖索引

2 當執行ALTER TABLE語句,並修改包含有位圖索引的列時,會使位圖索引失效

3 位圖索引在索引塊中存儲了索引鍵的值,然而,他們並不能完成用戶任何類型的檢查 

使用索引的目的

加快查詢速度,減少I/O操作

I/O操作:設備與cpu連接的接口電路的操作。

索引的種類

非唯一索引,唯一索引,位圖索引,局部有前綴分區索引,局部無前綴分區索引,

全局有前綴分區索引,散列分區索引,基於函數的索引

管理索引的準則

在表中插入數據後創建準則

在用SQL*LOADER(工具)或import工具插入或裝載數據後,建立索引比較有效

索引正確的表和列

列中的值相對比較唯一

取值範圍(大:B樹索引,小:位圖索引)

Date型列一般適合基於函數的索引

列中有許多空值,不適合建立索引

爲性能而安排索引列

經常一起使用多個字段檢索記錄,組合索引比單索引更有效。

把最常用的列放在最前面,例:dx_groupid_serv_id(groupid,serv_id),在where條件中使用groupid或serv_id,

查詢將使用索引,若僅用到serv_id字段,則索引無效。

合併/拆分不必要的索引 

限制每個表索引的數量

一個表可以有幾百個索引,但是對於頻繁的插入和更新表,索引越多系統CPU,I/O負擔就越重。

建議每張表不超過5個索引。

刪除不再需要的索引。

索引無效,集中表現在該使用基於函數的索引或位圖索引,而使用了B樹索引。

應用中的查詢不使用索引。

重建索引之前必須先刪除索引,若用alter index ...rebuild 重建索引,則不必刪除索引。

索引數據塊空間使用

創建索引時指定表空間,特別是在建立主鍵時,應明確指定表空間。

合理設定pctfress,注意:不能給索引指定pctused

pctfress:爲一個塊保留的空間百分比,表示數據塊在什麼情況下可以被insert,默認是10,

表示當數據塊的可用空間低於10%後,就不可以被insert了,只能被用於update。

即當使用一個bolck時,在達到pctfree之前,該block是一直可以被插入的,這個時候處在上升期。

pctused:是指當塊裏的數據低於多少百分比時,又可以重新被insert,一般默認是40,即40%,

即當數據低於40%時,又可以寫入新的數據,這個時候處在下降期。

考慮並行創建索引

對大表可以採取並行創建索引,在並行創建索引時,存儲參數被每個查詢服務器進程分別使用,

例如:initial爲1M,並行度爲8,則創建索引期間至少要消耗8M空間。

考慮用nologging創建索引

對大表創建索引時可以用弄logging來減少重做日誌。

節省重做日誌文的空間。

縮短創建索引的時間。

改善了並行創建大索引時的性能。

怎樣建立最佳索引

明確的創建索引

create index index_name on table_name (field_name)

tablespace tablespace_name

pctfree 5

initrans 2

maxtrans 255

storge

(

minextents 1

maxextents 16382

pctincrease 0

 )

initrans:每個塊都有一個塊首部。事務表中會建立一些條目來描述哪些事務將塊上的哪些行/元素鎖定。

這個事務表的初始大小由對象initrans設定指定。 對於表,這個值默認爲1,索引的initrans默認爲2。

創建基於函數的索引

常用語UPPER,LOWER,TO_CHAR(date)等函數分類上, 例

create index idx_func on emp(UPPER(ename)) tablespace tablespace_name

創建位圖索引

對於基數較小,且基數相對穩定的列建立索引時,首先應該考慮位圖索引,例

create bitmap index idx_bitm on class(classno) tablespace tablespace_name

明確地創建唯一索引

唯一索引:一種索引,不允許具有索引值相同的,從而禁止重複的索引或鍵值。

系統在創建該索引時檢查是否有重複的鍵值,並在每次使用insert和update語句添加數據時進行檢查。

可以用create unique index 語句來創建唯一索引,例

create unique index dept_unique_idx on dept(dept_no) tablespace idx_1;

創建與約束相關的索引

可以用using index字句,爲與unique和primary key約束相關的索引,例如:

alter table table_name

add constraint PK_primary_keyname primary key (field_name)

using index tablespace tablespace_name;

建立索引的代價

基礎表維護時,系統要同時維護索引,不合理的索引將嚴重影響系統資源,主要表現在CPU和I/0上

插入,更新,刪除數據產生大量db file sequential read鎖等待

db file sequential read:??db file sequential read等待事件有3個參數,file#,first block#,和block#數量。

在10g中,這等待事件受到用戶I/O等級別的影響。當處理db file sequential read等待事件的時候,牢記以下關鍵想法。

oracle進程需要一個當前不在SGA中的塊,等待數據塊從磁盤讀入到SGA中。

要看的倆個重要的數字是單獨會話和TIME_WAITED和AVERAGE_WAIT

重要db file sequential read等待時間最可能是一個應用問題。

下面是一些常見的索引限制問題

使用不等於操作符(<>,!=)

即使在列dept_id有一個索引,查詢語句扔然執行一次全表掃描

select * from dept where staff_num <> 1000;

但是開發中的確需要這樣的查詢,難道沒有解決問題的辦法了嗎?

有的!

通過把用or語法替代不等號進行查詢,就可以使用索引,以避免全表掃描,

上面的語句改成下面這樣的,就可以使用索引了。

select * from dept where staff_num < 1000 or dept_id > 1000;

使用函數

如果沒有使用基於函數的索引,那麼where子句中對存在索引的列使用函數時,會使優化器忽略掉這些索引,

下面的查詢就不會使用索引

select * from staff where trunc(birthdate) = '01-MAY-82'

但是把函數應用在條件上,索引是可以生效的, 把上面的語句改成下面的語句,就可以通過索引進行查找。

select * from staff where birthdate < (to_date('01-MAY-82') + 0.9999) 

下面的例子中,dept_id是一個varchar2型的字段, 在這個字段上有索引,但是下面的語句會執行全盤掃描。

select * from dept where dept_id = 900198

這是因爲oracle 會自動把where 子句換成to_number(DEPT_ID) = 900198 , 就是限制了索引的使用。

把語句改成select * from dept where dept_id = '900198'   語句就會使用索引。

使用like子句查詢時,數據需要把所有的記錄都遍歷來進行判斷,索引不能發揮作用,這種情況也要儘量避免。

如果能不用到排序,則儘量避免排序。

用到排序的情況有集合操作。

union,minus,intersect,注意:union all是不排序的。

order by , group by, distinct , in 有的時候會用到排序

確實要排序的時候也儘量要排序小數據量 ,儘量讓排序在內存中執行。


















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