2014-06-01 BaoXinjian算法
1、摘要數據庫
在PLSQL查詢優化中,使用和接觸最多的應該是索引Index這個概念,我的也以爲對Index選擇和優化是程式優化過程當中比較重要的概念,特別是剛開始接觸PLSQL性能優化性能優化
索引的一些概念oracle
索引的鏈接方式函數
索引的分類oop
索引的中Hints使用性能
創建索引的代價測試
有些狀況下雖然在查詢欄位中定義了index,可是PLSQL並無走該欄位的索引,由於Oracle在解析計劃時一種基於Role,一種是基於Cost有些狀況下走Index的效率比全表掃秒更低,並非建了Index,PLSQL性能會成倍提升,更糟的狀況下,建Index還會致使性能比原來無索引更糟,這裏有個理解誤區,因此稍微提一下 ;)優化
並且,有時候你創建的索引可能應爲空間或其餘緣由被失效後,因此會致使某些程式本來沒有任何問題,忽然出現性能問題,並且是很是大性能問題,因此對EBS DBA也有較高的要求,能監控一些系統異常
ui
2、索引的鏈接方式
1. Hash Join
2. Nested Loops
3. Merge Join
具體解析
1. Hash Join
(1).概述
i. 讀取一個表的資料,並將放置到內存中,並創建惟一關鍵字的位圖索引
ii. 讀取另外一個表,和內存中表經過Hash算法進行比較
(2).適用對象
i. 大表鏈接小表
ii. 兩個大表
2. Nested Loops
(1).概述
i. 循環外表記錄
ii. 進行逐個比對和內標的鏈接是否符合條件
(2).適用對象
小表驅動大表,返回較少的結果集
3. Merge Join
(1).概述
i. 兩個表進行table access full
ii. 對table access full的結果進行排序
iii. 進行merge join對排序結構進行合併
(2).適用對象
經過rowid訪問數據
3、索引的分類
1. B-樹索引
2. 反向索引
3. 降序索引
4. 位圖索引
5. 函數索引
6. 創建索引後須要分析索引才能是索引生效
7. 主鍵和惟一性索引的區別
具體解析
1. B-樹索引
(1).概述
最經常使用的索引結構,默認創建的索引就是這種結構
適用於高基數數據列(該列的值大多不同)
(2).創建方式
CREATE INDEX index_name ON wip_entities (wip_entity);
2. 反向索引
(1).概述
(2).創建方式
3. 降序索引
(1).概述
適用於須要降序排列的列
(2).創建方式
CREATE INDEX index_name ON wip_entities (wip_entity DESC);
4. 位圖索引
(1).概述
適用於低基數數據列(該列的值大可能是同樣)
(2).創建方式
CREATE BITMAP INDEX index_name ON wip_entities (sex);
5. 函數索引
(1).概述
適用於該列須要適用函數的列
(2).創建方式
CREATE INDEX index_name ON wip_entities (TRUNC(creation_date));
6. 分析索引
ANALYZE INDEX index_name COMPUTE STATISTICS;
7. 主鍵和惟一性索引的區別
(1). 主鍵是約束,惟一性索引只是一個索引
(2). 主鍵不能夠爲空,惟一性能夠爲空
四. 索引的中Hints使用 - 強制索引
1. 創建一個測試表,和測試索引
1 CREATE TABLE dba_name ( 2 3 username VARCHAR(100), 4 5 password VARCHAR(100) 6 7 ) ; 8 9 CREATE INDEX index_t ON dba_name(username) ;
2. 方法比較
(1). 未使用強制索引
SELECT *
FROM dba_name
WHERE username = 'BAOXINJIAN'
(2). 使用過強制索引
SELECT /*+ index(t index_t) */
*
FROM dba_name t
WHERE username = 'BAOXINJIAN'
(3). 有些狀況下雖然在查詢欄位中定義了index,可是PLSQL並無走該欄位的索引,由於Oracle在解析計劃時一種基於Role,一種是基於Cost
有些狀況下走Index的效率比全表掃秒更低,並非建了Index,PLSQL性能會成倍提升,更糟的狀況下,建Index還會致使性能比原來無索引更糟,這裏有個理解誤區,因此稍微提一下 ;)
五. 索引一些規則
一、權衡索引個數與DML之間關係,DML也就是插入、刪除數據操做。
這裏須要權衡一個問題,創建索引的目的是爲了提升查詢效率的,但創建的索引過多,會影響插入、刪除數據的速度,由於咱們修改的表數據,索引也要跟着修改。這裏須要權衡咱們的操做是查詢多仍是修改多。
二、把索引與對應的表放在不一樣的表空間。
當讀取一個表時表與索引是同時進行的。若是表與索引和在一個表空間裏就會產生資源競爭,放在兩個表這空就可並行執行。
三、最好使用同樣大小是塊。
Oracle默認五塊,讀一次I/O,若是你定義6個塊或10個塊都須要讀取兩次I/O。最好是5的整數倍更能提升效率。
四、若是一個表很大,創建索引的時間很長,由於創建索引也會產生大量的redo信息,因此在建立索引時能夠設置不產生或少產生redo信息。只要表數據存在,索引失敗了大不了再建,因此能夠不須要產生redo信息。
五、建索引的時候應該根據具體的業務SQL來建立,特別是where條件,還有where條件的順序,儘可能將過濾大範圍的放在後面,由於SQL執行是從後往前的
六. 索引的操做
改變索引:
SQL> alter index employees_last _name_idx storage(next 400K maxextents 100);索引建立後,感受不合理,也能夠對其參數進行修改。詳情查看相關文檔
2. 調整索引的空間:
2.1 新增長空間
SQL> alter index orders_region_id_idx allocate extent (size 200K datafile '/disk6/index01.dbf');
2.2 釋放空間
SQL> alter index oraers_id_idx deallocate unused;
索引在使用的過程當中可能會出現空間不足或空間浪費的狀況,這個時候須要新增或釋放空間。上面兩條命令完成新增與釋放操做。關於空間的新增oracle能夠自動幫助,若是瞭解數據庫的狀況下手動增長能夠提升性能。
3. 從新建立索引:
所引是由oracle自動完成,當咱們對數據庫頻繁的操做時,索引也會跟着進行修改,當咱們在數據庫中刪除一條記錄時,對應的索引中並無把相應的索引只是作一個刪除標記,但它依然佔據着空間。除非一個塊中全部的標記全被刪除的時,整個塊的空間纔會被釋放。這樣時間久了,索引的性能就會降低。這個時候能夠從新創建一個乾淨的索引來提升效率。
SQL> alter index orders_region_id_idx rebuild tablespace index02;經過上面的命令就能夠重現創建一個索引,oracle重創建索引的過程:
一、鎖表,鎖表以後其餘人就不能對錶作任何操做。
二、建立新的(乾淨的)臨時索引。
三、把老的索引刪除掉
四、把新的索引從新命名爲老索引的名字
五、對錶進行解鎖。
4. 移動所引:
其實,咱們移動索引到其它表空間也一樣使用上面的命令,在指定表空間時指定不一樣的表空間。新的索引建立在別位置,把老的幹掉,就至關於移動了。
SQL> alter index orders_region_id_idx rebuild tablespace index03;
5. 在線從新建立索引:
上面介紹,在建立索引的時候,表是被鎖定,不能被使用。對於一個大表,從新建立索引所須要的時間較長,爲了知足用戶對錶操做的需求,就產生的這種在線從新建立索引。
SQL> alter index orders_id_idx rebuild online;建立過程:
一、鎖住表
二、建立立臨時的和空的索引和IOT表用來存在on-going DML。普通表存放的鍵值,IOT所引表直接存放的表中數據;on-gong DML也就是用戶所作的一些增刪改的操做。
三、對錶進行解鎖
四、從老的索引建立一個新的索引。
五、IOT表裏存放的是on-going DML信息,IOT表的內容與新建立的索引合併。
六、鎖住表
七、再次將IOT表的內容更新到新索引中,把老的索引幹掉。
八、把新的索引從新命名爲老索引的名字
九、對錶進行解鎖
6. 整合索引碎片:
如上圖,在不少索引中有剩餘的空間,能夠經過一個命令把剩餘空間整合到一塊兒。
SQL> alter index orders_id_idx coalesce;
7. 刪除索引:
SQL> drop index hr.departments_name_idx;
七. 索引的分析
檢查所引的有效果,前面介紹,索引用的時間久了會產生大量的碎片、垃圾信息與浪費的剩餘空間了。能夠經過從新建立索引來提升所引的性能。
能夠經過一條命令來完成分析索引,分析的結果會存放在在index_stats表中。
1. 查看存放分析數據的表:
SQL> select count(*) from index_stats;
COUNT(*)
----------
0
2. 執行分析索引命令:
SQL> analyze index my_bit_idx validate structure;
Index analyzed.
再次查看 index_stats 已經有了一條數據
SQL> select count(*) from index_stats;
COUNT(*)
----------
1
3. 把數據查詢出來:
SQL> select height,name,lf_rows,lf_blks,del_lf_rows from index_stats;
HEIGHT NAME LF_ROWS LF_BLKS DEL_LF_ROWS
---------- ---------------------------------------------------------------------- ---------- -----------
2 MY_BIT_IDX 1000 3 100 分析數據分析:
4. 分析
八. 索引的優勢缺點
1. 索引的優勢
2. 索引的缺點
九. 未走索引的狀況
如下是使用索引不當所引發的不走索引的幾種常見狀況:
1. Index on t(x,y)但where 條件中只有y字段。
一般狀況會進行全表掃描。
2. select count(*) from t一般因爲索引比table小,oracle會進行index full scan。
但若是索引字段含有NULL值,則不會走索引,由於索引值不包含null,若是進行index full scan統計值就不許確了。
3. select * from t where f(index_column)=value
若是不是函數索引,where條件在索引字段上進行函數操做則不走索引
4. select * from t where indexed_column=5 字段類型需轉換。
例如indexed_column是字符但where條件中用了數字
5. oracle優化器認爲全表掃描比走索引效率更高。
這種狀況下oracle選擇全表掃描。若是開發人員以爲有必要走索引,可使用hint強制走索引
6. 未及時對錶進行analyze,statistics不許確。
例如原先是小表,後來數據量大增。因爲statistics還是舊的,oracle優化器會選擇不走索引
********************做者: 鮑新建********************