索引與表相似,也能夠分區;html
分區索引分爲兩類:數據庫
下面就來詳細解析一下這兩類索引。安全
一:Locally partitioned index(局部分區索引)數據結構
1. 概念:併發
局部分區索引隨表對索引完成相應的分區(即索引會使用與底層表相同的機制分區),每一個表分區都有一個索引分區,而且只索引該表分區。app
如圖,若一個表被劃分爲AB兩個分區,則局部分區索引A就只索引A分區中的數據,局部分區索引B只索引B分區中的數據;less
2. 分類:分佈式
局部分區索引又分爲兩類:優化
Ⅰ:局部前綴索引:以分區鍵做爲索引定義的第一列spa
Ⅱ:局部非前綴索引:分區鍵沒有做爲索引定義的第一列
示例語句:
create table local_index_example ( id number(2), name varchar2(50), sex varchar2(10) ) partition by range (id) ( partition part_1 values less than (5), partition part_2 values less than (10) ) --建立局部前綴索引;分區鍵(id)做爲索引定義的第一列 create index local_prefixed_index on local_index_example (id, name) local; --建立局部非前綴索引;分區鍵未做爲索引定義的第一列 create index local_nonprefixed_index on local_index_example (name, id) local;
注意:判斷局部索引是前綴仍是非前綴的只須要看分區鍵是否做爲索引定義的第一列
3. 何時該使用前綴索引?何時該使用非前綴索引?
對於該使用前綴仍是非前綴索引,這徹底取決於你的實際需求,你應該儘可能從實際角度出發選擇合適的索引方式以充分利用到其分區消除的特性。
若是查詢首先訪問索引的話,它可否實現分區消除徹底取決於查詢中使用的謂詞(即Where篩選條件);
好比用上面的 local_index_example 表舉例,現有兩個查詢:
①: select … from local_index_example where id = :id and name = :name;
②: select … from local_index_example where name = :name;
對於以上兩個查詢來講,若是查詢第一步是走索引的話,則:
局部前綴索引 local_prefixed_index 只對 ① 有用;
局部非前綴索引 local_nonprefixed_index 則對 ① 和 ② 均有用;
若是你有多個相似 ① 和 ② 的查詢的話,則能夠考慮創建局部非前綴索引;若是日常多使用查詢 ① 的話,則能夠考慮創建局部前綴索引;
總之,重點是你要儘量保證查詢包含的謂詞容許索引分區消除
-------------------延伸閱讀:綁定變量(bind variable)--------------------
綁定變量是查詢中的一個佔位符,形如 :xxx 。
例如,要獲取 emp 表中 empno 爲 123 的記錄,你能夠執行以下兩種查詢:
①: select * from emp where empno = 123;
②: 先將綁定變量 :empno 的值設置爲 123,再執行查詢 select * from emp where empno = :empno;
第一種查詢使用了 123 這樣一個直接量(常量),若是有多個這樣的查詢的話,則每個查詢對數據庫來講都是一個全新的查詢,Oracle每次都會對查詢進行解析、限定(命名解析)、安全性檢查、優化等(簡單地講,就是每次執行時都要先編譯);
第二種查詢使用了 :empno 這樣一個綁定變量,變量值在查詢時動態指定,這個查詢只會在第一次時編譯,隨後Oracle會把查詢計劃存儲在一個共享池中方便之後重用,如此當之後再傳入不一樣的 empno 值進行查詢時,Oracle會直接調用第一次解析好的這個執行計劃進行執行,這樣查詢效率將大幅提高
------------------------------------------------------------------------
4. 局部索引的惟一性
Oracle只保證索引分區內部的惟一性,跨分區的惟一性沒法保證。
若是你想使用局部索引實現惟一性約束的話,則必須讓分區鍵實現惟一性約束(UNIQUE 或 PRIMARY KEY)
二:Globally partitioned index(全局分區索引)
1. 概念:
全局分區索引,顧名思義,就是針對整個表空間(全局)來講的。
在此,索引按範圍(Range)或散列(Hash,Oracle 10g中引入)進行分區,一個分區索引(全局)可能指向任何(或所有的)表分區。
對於全局分區索引來講,索引的實際分區數可能不一樣於表的分區數量;
全局索引的分區機制有別於底層表,例如表能夠按 done_date 列劃分爲10個分區,表上的一個全局索引能夠按 id 列劃分爲5個分區。
與局部索引不一樣,全局索引只有一類,即全局前綴索引(prefixed global index),索引分區鍵必須做爲索引定義的第一列,不然執行會報錯。
用例語句:
--建立示例表,按id進行範圍分區 create table global_index_example ( id number(2), name varchar2(50), age number(2) ) partition by range (id) ( partition part_1 values less than (5), partition part_2 values less than (10) ) --建立按age進行範圍分區的全局分區索引 create index global_index on global_index_example(age) global partition by range (age) ( partition index_part_1 values less than (20), partition index_part_2 values less than (maxvalue) )
注意:
全局索引要求最高分區(即最後一個分區)必須有一個值爲 maxvalue 的最大上限值,這樣能夠確保底層表的全部行都能放在這個索引中;
通常狀況下,大多數分區操做(如刪除一箇舊分區)都會使全局索引無效,除非重建全局索引,不然沒法使用
2. 全局索引的使用:
1) 數據倉庫
許多數據倉庫系統都存在大量的數據出入,如典型的數據「滑入滑出」(即刪除表中最舊的分區,併爲新加載的數據增長一個新分區);
這個過程涉及:
在 Oracle 9i 以前,對於建立的全局索引來講,這樣增刪分區的過程,意味着該全局索引的失效,你將不得不在最後花費至關長的時間重建全局索引;
在 Oracle 9i 以後,你能夠在分區操做期間使用 UPDATE GLOBAL INEXES 子句來維護全局索引,這意味着當你在分區上執行刪除、分解或其餘操做時,Oracle會對原先創建的全局索引執行必要的修改,以保證它是最新的
使用示例:
--刪除global_index_example表中的part_1分區,同時同步維護全局索引 alter table global_index_example drop partition part_1 update global indexes;
使用 UPDATE GLOBAL INEXES子句後,在刪除一個分區時,必須刪除可能指向該分區的全部全局索引條目;
執行表與分區的交換時,必須刪除指向原數據的全部全局索引條目,再插入指向剛加載的數據的新條目;
如此一來 ALTER 命令執行的工做量會大幅增長;
注意:使用 UPDATE GLOBAL INDEXES,將不能繞過 undo 或 redo 生成;
小結:
分區操做執行完成後重建全局索引方式佔用的數據庫資源更少,所以完成的相對「更快」,可是會帶來顯著的「停機時間」(重建索引時會有一個可觀的不可用窗口);
在分區操做執行的同時執行 UPDATE GLOBAL INEXES 子句方式會佔用更多的資源,且可能須要花費更長的時間才能完成操做,但好處是不會帶來任何的停機時間
----------------------------延伸閱讀:redo(重作信息) 與 undo(撤銷信息)------------------------------
什麼是redo?
redo log file(重作日誌文件),是數據庫的事務日誌。
Oracle維護着兩類重作日誌文件:在線(online)重作日誌文件和歸檔(archived)重作日誌文件,這兩類重作日誌文件用於實例失敗或是介質失敗時的數據恢復;
若是數據庫所在主機忽然斷電致使實例失敗,則Oracle會使用在線重作日誌將系統剛好恢復到掉電以前的時間點;
若是硬盤出現故障(即介質失敗),Oracle會使用歸檔重作日誌和在線重作日誌將硬盤上的數據恢復到適當的時間點;
另外若是你無心地刪除了某些重要信息並提交了這個操做,那麼能夠恢復受影響數據的一個備份,並使用在線和歸檔重作日誌文件把它恢復到以前的一個時間點;
重作日誌多是數據庫中最重要的恢復結構,但同時其餘部分(如undo段、分佈式事務恢復等)也不可或缺,重作日誌是數據庫區別於傳統文件系統的一個主要特徵;
什麼是undo?
當你對數數據執行修改(增、刪等)時,數據庫會生成undo信息,萬一你執行的事務或語句因爲某些緣由失敗時,或者你用一條 rollback 語句請求回滾時,數據庫就能夠利用這些undo信息將數據返回到修改前的樣子。
redo用於在失敗時恢復事務,undo則用於取消一條語句或一組語句的做用;
undo信息存儲在數據庫內部一組特殊的段中(undo segment);
注意:
undo並非使數據庫物理地恢復到執行語句或事務以前的樣子,數據庫只是邏輯地恢復到原來的樣子,全部修改都被邏輯地取消,可是數據結構以及數據庫塊在回滾後可能還與回滾前保持一致;
由於在多用戶系統中,可能會有數百或數千個併發事務,不只僅你的事務在修改一些塊,其餘許多人的事務可能也在修改這些塊;所以,不能簡單地將一個塊放回到你的事務開始前的樣子,這樣極可能會撤銷掉其餘人的事務工做。
好比:
假設你的事務執行了一個 insert 語句,這條語句致使分配了一個新區段;
經過執行這個 insert,你將會得到一個新的數據庫塊,並在格式化該塊後往其中放入一些數據;
此時,可能出現另外某個事務,它也往這個塊中插入數據;若是要回滾你的事務,顯然不能取消對這個數據庫塊已有的格式化和空間分配,不然會影響到另外的那個事務的工做。
所以在回滾時,Oracle實際上會作與先前邏輯上相反的工做,即:
對於每一個 insert,會執行一個 delete;
對於每一個 delete,會執行一個 insert;
對於每一個 update,會執行一個「反update」,或者是執行另外一個 update 將修改前的行放回去;
還有一點須要特別注意:undo生成對於直接路徑操做(即便用append提示進行insert)不適用,直接路徑操做能繞過表上的undo生成;
如此,redo與undo共同協做以保證數據的完整與安全性
--------------------------------------------------------------------------------------------------
2) OLTP系統
OLTP系統的特色是會頻繁出現許多小的讀寫事務,通常在OLTP系統中,首要的是須要快速訪問所需的行,其次數據的完整性、可用性也很是重要。
在OLTP系統中,不少狀況下全局索引頗有意義,好比當表按一列分區後,你可能還須要經過其餘列來快速訪問數據,如此即可以考慮在這些列上創建全局索引。
原文來自:https://www.cnblogs.com/Dreamer-1/p/6132776.html