Oracle 数据库 各种索引类型 简单介绍
各種Oracle索引類型介紹
邏輯上: Single column 單行索引 Concatenated 多行索引 Unique 唯一索引 NonUnique 非唯一索引 Function-based函數索引 Domain 域索引物理上: Partitioned 分區索引 NonPartitioned 非分區索引 B-tree: Normal 正常型B樹 Rever Key 反轉型B樹 Bitmap 位圖索引索引結構: B-tree: 適合與大量的增、刪、改(OLTP); 不能用包含OR操作符的查詢; 適合高基數的列(唯一值多) 典型的樹狀結構; 每個結點都是數據塊; 大多都是物理上一層、兩層或三層不定,邏輯上三層; 葉子塊數據是排序的,從左向右遞增; 在分支塊和根塊中放的是索引的范圍; Bitmap: 適合與決策支持系統; 做UPDATE代價非常高; 非常適合OR操作符的查詢; 基數比較少的時候才能建位圖索引;樹型結構: 索引頭 開始ROWID,結束ROWID(先列出索引的最大范圍) BITMAP 每一個BIT對應著一個ROWID,它的值是1還是0,如果是1,表示著BIT對應的ROWID有值 1. b-tree索引 Oracle數據庫中最常見的索引類型是b-tree索引,也就是B-樹索引,以其同名的計算科學結構命名。CREATE INDEX語句時,默認就是在創建b-tree索引。沒有特別規定可用于任何情況。 2. 位圖索引(bitmap index) 位圖索引特定于該列只有幾個枚舉值的情況,比如性別字段,標示字段比如只有0和1的情況。 3. 基于函數的索引 比如經常對某個字段做查詢的時候是帶函數操作的,那么此時建一個函數索引就有價值了。 4. 分區索引和全局索引 這2個是用于分區表的時候。前者是分區內索引,后者是全表索引 5. 反向索引(REVERSE) 這個索引不常見,但是特定情況特別有效,比如一個varchar(5)位字段(員工編號)含值 (10001,10002,10033,10005,10016..) 這種情況默認索引分布過于密集,不能利用好服務器的并行 但是反向之后10001,20001,33001,50001,61001就有了一個很好的分布,能高效的利用好并行運算。 6.HASH索引 HASH索引可能是訪問數據庫中數據的最快方法,但它也有自身的缺點。集群鍵上不同值的數目必須在創建HASH集群之前就要知道。需要在創建HASH集群的時候指定這個值。使用HASH索引必須要使用HASH集群。分類:?sql+數據庫性能優化,sql語句+數據庫,區別對比
https://www.cnblogs.com/langtianya/p/6655050.html
?
?
?
?
?
?
https://blog.csdn.net/mss359681091/article/details/52061307
轉
Oracle中的索引詳解
2016年07月29日 09:15:46?三天不學習?閱讀數:521
一、 ROWID的概念
存儲了row在數據文件中的具體位置:64位 編碼的數據,A-Z, a-z, 0-9, +, 和 /,
row在數據塊中的存儲方式
SELECT ROWID, last_name FROM hr.employees WHERE department_id = 20;
比 如:OOOOOOFFFBBBBBBRRR
OOOOOO:data object number, 對應dba_objects.data_object_id
FFF:file#, 對應v$datafile.file#
BBBBBB:block#
RRR:row#
Dbms_rowid包
SELECT dbms_rowid.rowid_block_number('AAAGFqAABAAAIWEAAA') from dual;
具 體到特定的物理文件
二、 索引的概念
1、 類似書的目錄結構
2、 Oracle 的“索引”對象,與表關聯的可選對象,提高SQL查詢語句的速度
3、 索引直接指向包含所查詢值的行的位置,減少磁盤I/O
4、 與所索引的表是相互獨立的物理結構
5、 Oracle 自動使用并維護索引,插入、刪除、更新表后,自動更新索引
6、 語法:CREATE INDEX index ON table (column[, column]...);
7、 B-tree結構(非bitmap):
[一]了解索引的工作原理:
表:emp
目標:查詢Frank的工資salary
建立索 引:create index emp_name_idx on emp(name);
?
[試驗]測試索引的作用:
1. 運行/rdbms/admin/utlxplan 腳本
2. 建立測試表
create table t as select * from dba_objects;
insert into t select * from t;
create table indextable
as select rownum id,owner,object_name,subobject_name,
object_id,data_object_id,object_type,created
from t;
3. set autotrace trace explain
4. set timing on
5. 分析表,可以得到cost
6. 查詢 object_name=’DBA_INDEXES’
7. 在object_name列上建立索引
8. 再查詢
[思考]索引的代價:
插入,更新
三、 唯一索引
1、 何時創建:當某列任意兩行的值都不相同
2、 當建立Primary Key(主鍵)或者Unique constraint(唯一約束)時,唯一索引將被自動建立
3、 語法:CREATE UNIQUE INDEX index ON table (column);
4、 演示
四、 組合索引
1、 何時創建:當兩個或多個列經常一起出現在where條件中時,則在這些列上同時創建組合索引
2、 組合索引中列的順序是任意的,也無需相鄰。但是建議將最頻繁訪問的列放在列表的最前面
3、 演示(組合列,單獨列)
五、 位圖索引
1、 何時創建:
列中有非常多的重復的值時候。例如某列保存了 “性別”信息。
Where 條件中包含了很多OR操作符。
較少的update操作,因為要相應的跟新所有的bitmap
2、 結構:位圖索引使用位圖作為鍵值,對于表中的每一數據行位圖包含了TRUE(1)、FALSE(0)、或NULL值。
3、 優點:位圖以一種壓縮格式存放,因此占用的磁盤空間比標準索引要小得多
4、 語法:CREATE BITMAP INDEX index ON table (column[, column]...);
5、 掩飾:
create table bitmaptable as select * from indextable where owner in('SYS','PUBLIC');
分析,查找,建立索引,查找
六、 基于函數的索引
?? 1、 何時創建:在WHERE條件語句中包含函數或者表達式時
2、 函數包括:算數表達式、PL/SQL函數、程序包函數、SQL函數、用戶自定義函數。
3、 語法:CREATE INDEX index ON table (FUNCTION(column));
4、 演示
必須要分析表,并且 query_rewrite_enabled=TRUE
或者使用提示/*+ INDEX(ic_index)*/
七、 反向鍵索引
目的:比如索引值是一個自動增長的列:
多個用戶對集中在少數塊上的索引行進行修改,容易引起資源的爭用,比如對數據塊的等待。此時建立反向索 引。
性能問題:
語法:
重建為標準索引:反之不行
八、 鍵壓縮索引
比如表landscp的數據如下:
site feature job
Britten Park, Rose Bed 1, Prune
Britten Park, Rose Bed 1, Mulch
Britten Park, Rose Bed 1,Spray
Britten Park, Shrub Bed 1, Mulch
Britten Park, Shrub Bed 1, Weed
Britten Park, Shrub Bed 1, Hoe
……
查詢時,以上3列均在where條件中同時出現,所以建立基于以上3列的組合索引。但是發現重復值很多,所以考慮壓縮特性。
Create index zip_idx
on landscp(site, feature, job)
compress 2;
將索引項分成前綴(prefix)和后綴(postfix)兩部分。前兩項被放置到前綴部分。
Prefix 0: Britten Park, Rose Bed 1
Prefix 1: Britten Park, Shrub Bed 1
實際所以的結構為:
0 Prune
0 Mulch
0 Spray
1 Mulch
1 Weed
1 Hoe
特點:組合索引的前綴部分具 有非選擇性時,考慮使用壓縮。減少I/O,增加性能。
九、 索引組織表(IOT)
將表中的數據按照索 引的結構存儲在索引中,提高查詢速度。
犧牲插入更新的性能,換取查詢 性能。通常用于數據倉庫,提供大量的查詢,極少的插入修改工作。
必須指定主鍵。插入數據時,會根據主鍵列進行B樹索引排序,寫入磁盤。
十、 分區索引
簇:
A cluster is a group of tables that share the same data blocks because they share common columns and are often used together.
?
https://blog.csdn.net/mss359681091/article/details/52061307
?
?
?
?
?
?
Oracle:索引列壓縮的分析對比
2011-09-21 13:39 by Tracy.,?2315?閱讀,?0?評論,?收藏,?編輯
首先,我們結合index_stats得到的索引分析數據看一下,在不同索引列壓縮情況下的效果。然后統一總結實驗效果。
1.創建測試用表t_compress_index
create table t_compress_index as select * from all_objects;
2.不使用索引壓縮技術創建索引
sec@secooler> create?index?idx_t_compress_index on t(owner,object_type,object_name);
Index created.
sec@secooler> analyze index idx_t_compress_index validate structure;
Index analyzed.
sec@secooler> select height, lf_blks, br_blks, btree_space, opt_cmpr_count, opt_cmpr_pctsave from index_stats;
HEIGHT LF_BLKS BR_BLKS BTREE_SPACE OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
------ ------- ------- ----------- -------------- ----------------
2 64 1 519772 2 28
3.嘗試只使用第一列進行壓縮
sec@secooler> drop index idx_t_compress_index;
Index dropped.
sec@secooler> create index idx_t_compress_index on t(owner,object_type,object_name)?compress?1;
Index created.
sec@secooler> analyze index idx_t_compress_index validate structure;
Index analyzed.
sec@secooler> select height, lf_blks, br_blks, btree_space, opt_cmpr_count, opt_cmpr_pctsave from index_stats;
HEIGHT LF_BLKS BR_BLKS BTREE_SPACE OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
------ ------- ------- ----------- -------------- ----------------
2 56 1 455580 2 18
4.嘗試使用前兩列進行壓縮
sec@secooler> drop index idx_t_compress_index;
Index dropped.
sec@secooler> create index idx_t_compress_index on t(owner,object_type,object_name) compress 2;
Index created.
sec@secooler> analyze index idx_t_compress_index validate structure;
Index analyzed.
sec@secooler> select height, lf_blks, br_blks, btree_space, opt_cmpr_count, opt_cmpr_pctsave from index_stats;
HEIGHT LF_BLKS BR_BLKS BTREE_SPACE OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
------ ------- ------- ----------- -------------- ----------------
2 46 1 375660 2 0
5.嘗試使用前三列進行壓縮
sec@secooler> drop index idx_t_compress_index;
Index dropped.
sec@secooler> create index idx_t_compress_index on t(owner,object_type,object_name) compress 3;
Index created.
sec@secooler> analyze index idx_t_compress_index validate structure;
Index analyzed.
sec@secooler> select height, lf_blks, br_blks, btree_space, opt_cmpr_count, opt_cmpr_pctsave from index_stats;
HEIGHT LF_BLKS BR_BLKS BTREE_SPACE OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
------ ------- ------- ----------- -------------- ----------------
2 73 1 591444 2 36
6.注意:因為索引列之后三個,所以記住不能使用compress 4進行壓縮,這個是顯然滴~~
sec@secooler> drop index idx_t_compress_index;
Index dropped.
sec@secooler> create index idx_t_compress_index on t(owner,object_type,object_name) compress 4;
create index idx_t_compress_index on t(owner,object_type,object_name) compress 4
*
ERROR at line 1:
ORA-25194: invalid COMPRESS prefix length value
7.索引壓縮小結
(1)通過上面的這個演示過程,可以得到以下結論:
1)對前兩列進行壓縮效果最好
2)對全部的三列壓縮反倒比不使用壓縮技術耗用更多的索引空間,這與壓縮機制有關
3)要在實踐中反復的測試,得出最佳的壓縮系數
(2)索引壓縮缺點:
1.維護索引時,更耗時,因為需要更多的計算
2.查詢時,搜索索引需要較長的時間,因為需要更多的計算
3.需要更多的CPU處理索引
4.增加了塊競爭
(3)索引壓縮好處:
1.索引占用的磁盤空間少,這是顯然的
2.塊緩沖區緩存能存放更多的索引條目
3.緩存命中率較高
4.物理I/O較少
任何一種技術都是一種均衡各種資源后的產物,索引壓縮技術就充分的體現了這方的特點,需要在disk和CPU之間做到取舍與平衡,需要具體問題具體分析。
友情提示:如果聯合索引的前幾列存在大量的重復數據的時候,不妨使用一下索引壓縮技術。
-- The End --
魔獸就是毒瘤,大家千萬不要玩。
好文要頂?關注我?收藏該文??
Tracy.
關注 - 25
粉絲 - 24
+加關注
0
0
??上一篇:Oracle:在Oracle中使用鎖進行并發控制
??下一篇:轉:Oracle ASM 系列 小結
- 分類:?Oracle性能診斷
- ?
刷新評論刷新頁面返回頂部
https://www.cnblogs.com/sopost/archive/2011/01/09/2190057.html
?
?
?
?
?
?
轉
ORACLE 索引概述
2012年11月18日 23:01:55?zdwzzu2006?閱讀數:4869
索引是數據庫中一種可選的數據結構,她通常與表或簇相關。用戶可以在表的一列或數列上建立索引,以提高在此表上執行 SQL 語句的性能。就像本文檔的索引可以幫助讀者快速定位所需信息一樣,Oracle 的索引提供了更為迅速地訪問表數據的方式。正確地使用索引能夠顯著的減少磁盤 I/O。
? ? ? ? 用戶可以為一個表創建多個索引,只要不同索引使用的列或列的組合(combination of columns)不同即可。例如,下列語句中指定的列組合是有效的:
? ? ? ? CREATE INDEX employees_idx1 ON employees (last_name, job_id);
? ? ? ? CREATE INDEX employees_idx2 ON employees (job_id, last_name);
? ? ? ? Oracle 提供了各種類型的索引,她們能夠互為補充地提升查詢性能:
- 平衡樹索引(B-tree index)
- 平衡樹簇索引(B-tree cluster index)
- 哈希簇索引(hash cluster index)
- 反向鍵索引(reverse key indexes)
- 位圖索引(bitmap index)
- 位圖連接索引(bitmap join index)
? ? ? ? Oracle 還支持函數索引(function-based index),以及針對特定應用程序或程序模塊(cartridge)的域索引(domain index)。
? ? ? ??無論索引是否存在都無需對已有的 SQL 語句進行修改。索引只是提供了一種快速訪問數據的路徑,因此她只會影響查詢的執行速度。當給出一個已經被索引的數據值后,就可以通過索引直接地定位到包含此值的所有數據行。
? ? ? ??索引在邏輯上和物理上都與其基表(base table)是相互獨立的。用戶可以隨時創建(create)或移除(drop)一個索引,而不會影響其基表或基表上的其他索引。當用戶移除一個索引時,所有的應用程序仍然能夠繼續工作,但是數據訪問速度有可能會降低。作為一種獨立的數據結構,索引需要占用存儲空間。
? ? ? ??當索引被創建后,對其的維護與使用都是 Oracle 自動完成的。當索引所依賴的數據發生插入,更新,刪除等操作時,Oracle 會自動地將這些數據變化反映到相關的索引中,無需用戶的額外操作。
? ? ? ? 即便索引的基表中插入新的數據,對被索引數據的查詢性能基本上能夠保持穩定不變。但是,如果在一個表上建立了過多的索引,將降低其插入,更新,及刪除的性能。因為 Oracle 必須同時修改與此表相關的索引信息。
? ? ? ? 優化器可以使用已有的索引來建立(build)新的索引。這將加快新索引的建立速度。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
5.8.1 唯一索引和非唯一索引
? ? ? ? ?索引(index)可以是唯一(unique)的或非唯一(nonunique)的。在一個表上建立唯一索引(unique index)能夠保證此表的索引列(一列或多列)不存在重復值。而非唯一索引(nonunique index)并不對索引列值進行這樣的限制。
? ? ? ? Oracle 建議使用?CREATE UNIQUE INDEX?語句顯式地創建唯一索引(unique index)。通過主鍵(primary key)或唯一約束(unique constraint)來創建唯一索引不能保證創建新的索引,而且用這些方式創建的索引不能保證為唯一索引。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
5.8.2 復合索引
? ? ? ? ?復合索引(composite index)(也被稱為連結索引(concatenated index))是指創建在一個表的多列上的索引。復合索引內的列可以任意排列,她們在數據表中也無需相鄰。
? ? ? ??如果一個 SELECT 語句的 WHERE 子句中引用了復合索引(composite index)的全部列(all of the column)或自首列開始且連續的部分列(leading portion of the column),將有助于提高此查詢的性能。因此,索引定義中列的順序是很重要的。大體上說,經常訪問的列(most commonly accessed)或選擇性較大的列(most selective)應該放在前面。
? ? ? ? 一個常規的(regular)復合索引(composite index)不能超過 32 列,而位圖索引(bitmap index)不能超過 30 列。索引中一個鍵值(key value)的總長度大致上不應超過一個數據塊(data block)總可用空間的一半。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
5.8.3 索引和鍵
? ? ? ? 索引(index)與鍵(key)是連個不同的概念,但是這兩個術語經常被混用。索引是在數據庫中實際存儲的數據結構,用戶可以使用 SQL 語句對其進行創建(create),修改(alter),或移除(drop)。索引提供了一種快速訪問表數據的途徑。而鍵只是一個邏輯概念。鍵的概念主要在 Oracle 的完整性約束(integrity constraint)功能中使用,完整性約束用于保證數據庫中的業務規則(business rule)。
? ? ? ? 因為 Oracle 也會使用索引(index)來實現某些完整性約束(integrity constraint),因此索引與鍵(key)這兩個術語經常被混用。注意不要將二者混淆。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
5.8.4 索引和空值
? ? ? ? 對于一個數據表的兩行或多行,如果其索引列(key column)中全部非空(non-NULL)的值完全相同(identical),那么在索引中這些行將被認為是相同的;反之,在索引中這些行將被認為是不同的。因此使用?UNIQUE?索引可以避免將包含 NULL 的行視為相同的。以上討論并不包括索引列的列值(column value)全部為?NULL?的情況。
? ? ? ? Oracle 不會將索引列(key column)全部為?NULL?的數據行加入到索引中。不過位圖索引(bitmap index)是個例外,簇鍵(cluster key)的列值(column value)全部為?NULL?時也是例外。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
5.8.5 函數索引
? ? ? ??如果一個函數(function)或表達式(expression)使用了一個表的一列或多列,則用戶可以依據這些函數或表達式為表建立索引,這樣的索引被稱為函數索引(Function-Based Index)。函數索引能夠計算出函數或表達式的值,并將其保存在索引中。用戶創建的函數索引既可以是平衡樹類型(B-tree index)的,也可以是位圖類型(bitmap index)的。
? ? ? ? 用于創建索引的函數可以是一個數學表達式(arithmetic expression),也可以是使用了 PL/SQL 函數(PL/SQL function),包函數(package function),C 外部調用(C callout),或 SQL 函數(SQL function)的表達式。用于創建索引的函數不能包含任何聚合函數(ggregate function),如果為用戶自定義函數,則在聲明中必須使用?DETERMINISTIC關鍵字。如果在一個使用對象類型(object type)的列上建立函數索引,則可以使用此對象的方法(method)作為函數,例如此對象的 map 方法。用戶不能在數據類型為?LOB,REF,或嵌套表(nested table)的列上建立函數索引,也不能在包含?LOB,REF,或嵌套表等數據類型的對象類型列上建立函數索引。
5.8.5.1 使用函數索引
? ? ? ??如果一個 SQL 語句的 WHERE 子句中使用了函數,那么建立相應的函數索引(function-based index)是提高數據訪問性能的有效機制。表達式(expression)的結果經過計算后將被存儲在索引中。但是當執行?INSERT?和?UPDATE?語句時,Oracle 需要進行函數運算以便維護索引。
? ? ? ? 例如,如果用戶創建了以下函數索引:
? ? ? ? CREATE INDEX idx ON table_1 (a + b * (c – 1), a, b);
? ? ? ? 當 Oracle 處理如下查詢時就可以使用之前建立的索引:
? ? ? ? SELECT a FROM table_1 WHERE a + b * (c – 1) < 100;
? ? ? ? 使用?UPPER(column_name)?或?LOWER(column_name)?函數建立函數索引(function-based index)有助于與大小寫無關(case-insensitive)的查詢。例如創建以下函數索引:
? ? ? ? CREATE INDEX uppercase_idx ON employees (UPPER(first_name));
? ? ? ? 有助于提高以下查詢的性能:
? ? ? ? SELECT * FROM employees WHERE UPPER(first_name) = ‘RICHARD’;
5.8.5.2 函數索引的優化
? ? ? ??用戶必須為優化器(optimizer)收集關于函數索引(unction-based index)的統計信息(statistic)。否則處理 SQL 語句時將不會使用此索引。
? ? ? ? 當一個查詢的 WHERE 子句中含有表達式(expression)時,優化器可以對函數索引(function-based index)進行索引區間掃描(index range scan)。例如以下查詢:
? ? ? ? SELECT * FROM t WHERE a + b < 10;
? ? ? ? 如果使用表達式(expression)?a+b?建立的索引,優化器(optimizer)就能夠進行索引區間掃描(index range scan)。如果謂詞(predicate,即?WHERE?子句)產生的選擇性(selectivity)較低,則對區間掃描極為有利。此外,如果表達式的結果物化在函數索引內(function-based index),優化器將能更準確地估計使用此表達式的謂詞的選擇性。
? ? ??? 優化器(optimizer)能夠將 SQL 語句及函數索引(function-based index)中的表達式解析為表達式樹(expression tree)并進行比較,從而實現表達式匹配。這個比較過程是大小寫無關的(case-insensitive),并將忽略所有空格(blank space)。
5.8.5.3 函數索引的依賴性
? ? ? ??函數索引(function-based index)依賴于索引定義表達式中使用的函數。如果此函數為 PL/SQL 函數(PL/SQL function)或包函數(package function),當函數聲明(function specification)發生變化時,索引將失效(disabled)。
? ? ? ? 用戶需要被授予(grant)CREATE INDEX?或?CREATE ANY INDEX?權限才能創建函數索引(function-based index)。
? ? ? ? 要想使用函數索引(function-based index):
- 建立索引后,表必須經過分析(analyze)。
- 必須保證查詢的條件表達式不是?NULL?值, 因為?NULL?值不會被存儲到索引中。
? ? ? ? 以下各節將講述使用函數索引的其他需求。
5.8.5.3.1 DETERMINISTIC 函數
? ? ? ? 函數索引(function-based index)使用的用戶自定義函數(user-written function)必須聲明為?DETERMINISTIC,此關鍵字表明對于一定的輸入參數,此函數總會得到相同的輸出結果。
5.8.5.3.2 定義函數的權限
? ? ? ? 函數索引(function-based index)的所有者(owner)必須具備此索引定義中使用的函數的EXECUTE?權限。當?EXECUTE?權限被收回(revoke)后,Oracle 則將索引標識為?DISABLED。索引的所有者無須具備此函數的?EXECUTE WITH GRANT OPTION?權限,即可將索引所在表的SELECT?權限授予(grant)其他用戶。
5.8.5.3.3 解決函數索引的依賴性問題
? ? ? ? 函數索引(function-based index)依賴于她使用的所有函數。如果函數或函數所在包的聲明(specification)被修改過(或索引所有者對函數的?EXECUTE?權限被收回),將會出現以下情況:
- 索引被標記為?DISABLED。
- 如果優化器(optimizer)選擇了在標記為?DISABLED?的索引上執行查詢,那么此查詢將失敗
- 使用標記為?DISABLED?的索引而執行的 DML 操作將失敗,除非此索引同時被標記為UNUSABLE?且初始化參數(initialization parameter)?SKIP_UNUSABLE_INDEXES?被設為TRUE。
? ? ? ? 函數被修改之后,用戶可以使用?ALTER INDEX … ENABLE?語句將索引重新置為?ENABLE?狀態。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
5.8.6 索引是如何存儲的
? ? ? ??當用戶創建索引時,Oracle 會自動地在表空間(tablespace)中創建索引段(index segment)來存儲索引的數據。用戶可以通過以下方式控制索引段的空間分配和使用:
- 設置索引段的存儲參數(storage parameter)來控制如何為此索引段分配數據擴展(extent)
- 為索引段設置?PCTFREE?參數,來控制組成數據擴展的各個數據塊(data block)的可用空間情況。
? ? ? ? 索引段(index segment)使用的表空間(tablespace)既可以是索引所有者(owner)的默認表空間,也可以是在?CREATE INDEX?語句中指定的表空間。索引無需和其相關的表位于同一表空間中。相反,如果將索引與其相關表存儲在不同磁盤上能夠提升使用此索引的查詢性能,因為此時 Oracle 能夠并行地(parallel)訪問索引及表數據。
5.8.6.1 索引塊的格式
? ? ? ??一個數據塊(data block)內可用于存儲索引數據的空間等于數據塊容量減去數據塊管理開銷(overhead),索引條目管理開銷(entry overhead),rowid,及記錄每個索引值長度的 1 字節(byte)。
? ? ? ? 當用戶創建索引時,Oracle 取得所有被索引列的數據并進行排序,之后將排序后索引值和與此值相對應的 rowid 按照從下到上的順序加載到索引中。例如,以下語句:
? ? ? ? CREATE INDEX employees_last_name ON employees(last_name);
? ? ? ? Oracle 先將?employees?表按?last_name?列排序,再將排序后的? 列及相應的 rowid 按從下到上的順序加載到索引中。使用此索引時,Oracle 可以快速地搜索已排序的?last_name?值,并使用相應的 rowid 去定位包含用戶所查找的?last_name?值的數據行。
5.8.6.2 索引的內部結構
? ? ? ??Oracle 使用平衡樹(B-tree)存儲索引以便提升數據訪問速度。當不使用索引時,用戶必須對數據進行順序掃描(sequential scan)來查找指定的值。如果有 n 行數據,那么平均需要掃描的行為 n/2。因此當數據量增長時,這種方法的開銷將顯著增長。
? ? ? ? 如果將一個已排序的值列(list of the values)劃分為多個區間(range),每個區間的末尾包含指向下個區間的指針(pointer),而搜索樹(search tree)中則保存指向每個區間的指針。此時在 n 行數據中查詢一個值所需的時間為 log(n)。這就是 Oracle 索引的基本原理。
? ? ? ? 在一個平衡樹索引(B-tree index)中,最底層的索引塊(葉塊(leaf block))存儲了被索引的數據值,以及對應的 rowid。葉塊之間以雙向鏈表的形式相互連接。位于葉塊之上的索引塊被稱為分支塊(branch block),分枝塊中包含了指向下層索引塊的指針。如果被索引的列存儲的是字符數據(character data),那么索引值為這些字符數據在當前數據庫字符集(database character set)中的二進制值(binary value)。
? ? ? ??對于唯一索引(unique index),每個索引值對應著唯一的一個 rowid。對于非唯一索引(nonunique index),每個索引值對應著多個已排序的 rowid。因此在非唯一索引中,索引數據是按照索引鍵(index key)及 rowid 共同排序的。鍵值(key value)全部為?NULL?的行不會被索引,只有簇索引(cluster index)例外。在數據表中,如果兩個數據行的全部鍵值都為 NULL,也不會與唯一索引相沖突。
5.8.6.3 索引的屬性
? ? ? ??有兩種類型的索引塊:
- 用于搜索的分支塊(branch block)
- 用于存儲索引數據的葉塊(leaf block)
5.8.6.3.1 分支塊
? ? ? ??分支塊(branch block)中存儲以下信息:
- 最小的鍵值前綴(minimum key prefix),用于在(本塊的)兩個鍵值之間做出分支選擇
- 指向包含所查找鍵值的子塊(child block)的指針()
? ? ? ? 包含 n 個鍵值的分支塊(branch block)含有 n+1 個指針。鍵值及指針的數量同時還受索引塊(index block)容量的限制。
5.8.6.3.2 葉塊
? ? ? ? 所有葉塊(leaf block)相對于其根分支塊(root branch block)的深度(depth)是相同的。葉塊用于存儲以下信息:
- 數據行的鍵值(key value)
- 鍵值對應數據行的?ROWID
所有的 鍵值-ROWID?對(key and?ROWID?pair)都與其左右的兄弟節點(sibling)向鏈接(link),并按照(key,ROWID)的順序排序。
5.8.6.4 平衡樹結構的優勢
? ? ? ? 平衡樹數據結構(B-tree structure)具有以下優勢:
- 平衡樹(B-tree)內所有葉塊(leaf block)的深度相同,因此獲取索引內任何位置的數據所需的時間大致相同。
- 平衡樹索引(B-tree index)能夠自動保持平。
- 平衡樹內的所有塊容量平均在總容量的 3/4 左右。
- 在大區間(wide range)范圍內進行查詢時,無論匹配個別值(exact match)還是搜索一個區間(range search),平衡樹都能提供較好的查詢性能。
- 數據插入(insert),更新(update),及刪除(delete)的效率較高,且易于維護鍵值的順序(key order)
- 大型表,小型表利用平衡樹進行搜索的效率都較好,且搜索效率不會因數據增長而降低。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
5.8.7 索引唯一掃描
? ? ? ??索引唯一掃描(index unique scan)是效率最高的數據訪問方式之一。從平衡樹索引(B-tree index)中獲取數據時將采用此種方式。當一個唯一索引(采用平衡樹結構)的全部列都包含在查詢條件中,且查詢體條件表達式均為等號(equality)時,優化器將選擇使用索引唯一掃描。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
5.8.8 索引區間掃描
? ? ? ??當訪問選擇性較大的數據(selective data)時 Oracle 常進行索引區間掃描(index range scan)。掃描區間可以是封閉的(bounded)(兩端均封閉),也可以是不封閉的(unbounded)(一端或兩端均不封閉)。掃描所返回的數據按照索引列的升序進行排列,對于索引值相同的行將按?ROWID?的升序排列。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
5.8.9 鍵壓縮
? ? ??? 用戶利用鍵壓縮(key compression)可以將索引或索引表(index-organized table)中鍵值(column value)的部分內容進行壓縮,以便減少重復值帶來的存儲開銷。
? ? ? ? 一般來說,索引的一個鍵(key)通常由兩個片段(piece)構成:分組片段(grouping piece)及唯一片段(unique piece)。如果定義索引的鍵中不存在唯一片段,Oracle 會以 ROWID 的形式在此鍵的分組片段后添加一個唯一片段。鍵壓縮(key compression)就是將鍵的分組片段從鍵中拆分出來單獨存儲,供多個唯一片段使用。
5.8.9.1 索引鍵的前綴和后綴
? ? ??? 鍵壓縮(key compression)將一個索引鍵拆分為前綴(prefix entry)(即分組片段(grouping piece))和后綴(suffix entry)(即唯一片段(unique piece))。壓縮是通過一個索引塊(index block)中的多個后綴共享一個前綴來實現的。在平衡樹索引(B-tree index)中只有位于葉塊(leaf block)的鍵會被壓縮。在分支塊(branch block)內不必存儲鍵的后綴,因此其中的鍵也無需壓縮。
? ? ? ? 鍵壓縮(key compression)只能在每個索引塊(index block)內分別實現,而不能跨多個索引塊。壓縮后每個索引行(index row)只保存后綴(suffix entry),而每個后綴將引用一個共享的前綴(prefix entry),后綴與其共享的前綴必須位于同一索引塊內。
? ? ? ? 默認情況下,前綴(prefix entry)由除去最后一列之外的其他鍵列(key column)構成。例如,一個索引鍵(index key)由(column1,column2,column3)3 列構成,則默認的前綴為(column1, column2)。如一組索引值為(1,2,3),(1,2,4),(1,2,7),(1,3,5),(1,3,4),(1,4,4),則其中重復出現的前綴 (1,2),(1,3) 將被壓縮。
? ? ? ? 用戶也可以手工設定前綴長度(prefix length),即前綴所包含的列數。例如,如果用戶設定前綴長度為 1,則在上述例子中,column1 為前綴,(column2,column3)為后綴,其中重復出現的前綴 1 將被壓縮。
? ? ??? 非唯一索引(nonunique index)的最大前綴長度(prefix length)為鍵列的個數,而唯一索引(unique index)的最大前綴長度為鍵列的個數減 1。
? ? ? ? 應用鍵壓縮(key compression)后,生成索引時,如果一個鍵值(key value)的前綴(prefix entry)在索引塊(index block)中不存在,此前綴才會被寫入索引塊中。一個前綴被寫入后立即就可以被此索引塊內的后綴(suffix entry)共享,直到所有引用此前綴的后綴都被刪除為止。
5.8.9.2 性能上及存儲上的考慮
? ? ? ??鍵壓縮(key compression)能夠節約大量存儲空間,因此用戶可以在一個索引塊(index block)內存儲更多的索引鍵(index key),從而減少 I/O,提高性能。
? ? ??? 鍵壓縮(key compression)能夠減少索引所需的存儲空間,但索引掃描時需要重構(reconstruct)鍵值(key value),因此增加了 CPU 的負擔。此外鍵壓縮也會帶來一些存儲開銷,每個前綴(prefix entry)需要 4 字節(byte)的管理開銷。
5.8.9.3 使用鍵壓縮
? ? ? ? 鍵壓縮(key compression)在多種情況下都能夠發揮作用,例如:
- 對于非唯一索引(nonunique index),Oracle 會在每個重復的索引鍵(index key)之后添加 rowid 以便區分。如果使用了鍵壓縮,在一個索引塊(index block)內,Oracle 只需將重復的索引鍵作為前綴((prefix entry))存儲一次,并用各行的 rowid 作為后綴(suffix entry)。
- 唯一索引(nonunique index)中也存在相同的情況。例如唯一索引(stock_ticker,transaction_time)的含義是(項目,時間戳),通常數千條記錄中stock_ticker?的值是相同的,但她們對應的?transaction_time?值各不相同。使用了鍵壓縮后,一個索引塊中每個?stock_ticker?值作為前綴只需存儲一次,而各個transaction_time?值則作為后綴存儲,并引用一個共享的?stock_ticker?前綴。
- 在一個包含?VARRAY?或?NESTED TABLE?數據類型(datatype)的索引表(index-organized table)中,這些collection 類型中各個元素(element)的對象標識符(object identifier)是重復的。用戶可以使用鍵壓縮以避免重復存儲這些對象標識符。
? ? ? ? 有些情況無法使用鍵壓縮(key compression)。例如,一個只有一個索引鍵(index key)的唯一索引(unique index)就無法使用鍵壓縮,因為索引鍵中不存在可供共享的分組片段(grouping piece)。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
5.8.10 逆序鍵索引
? ? ? ? 用戶可以創建逆序鍵索引(reverse key index),此處的逆序指索引列值(index key value)得各個字節(byte)按倒序排列,而非索引列(index key)逆序排列。在 RAC 環境中,使用這樣的排列方式可以避免由于對索引的修改集中在一小部分葉塊(leaf block)上而造成的性能下降。通過使索引的鍵值逆序排列,可以使插入操作分布在索引的全部葉塊中。
? ? ??? 使用逆序鍵索引(reverse key index)后將無法對此索引進行索引區間掃描(index range scanning),因為在逆序鍵索引 中,詞匯上(lexically)相鄰的索引鍵(index key)在存儲上未必相鄰。因此在逆序鍵索引 上只能進行確定鍵掃描(fetch-by-key scan)或全索引掃描(full-index scan)。
? ? ? ? 有些情況下,使用逆序鍵索引(reverse key index)可以令 RAC 環境下的 OLTP 應用效率更高。例如,為一個 e-mail 應用中的所有郵件進行索引:由于用戶可能保存舊的郵件,因此索引必須做到既能快速訪問最新郵件,也能快速訪問舊郵件。
? ? ? ? 用戶使用?REVERSE?就可以輕易地創建逆序鍵索引(reverse key index)。在?CREATE INDEX語句中使用?REVERSE?關鍵字作為創建索引的選項:
? ? ? ? CREATE INDEX i ON t (a,b,c) REVERSE;
? ? ? ? 用戶也可以在?REBUILD?子句后添加?NOREVERSE?關鍵字將一個逆序鍵索引(reverse key index)轉換為常規的索引:
? ? ? ? ALTER INDEX i REBUILD NOREVERSE;
? ? ? ? 如果?REBUILD?子句后沒有使用?NOREVERSE?關鍵字,那么逆序鍵索引(reverse key index)被重建后仍將保持逆序。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ???
5.8.11 位圖索引
? ? ? ??索引的目標是為用戶提供指向包含特定鍵值(key value)的數據行的指針。在常規的索引中,Oracle 將各行的鍵值及與此鍵值對應的一組 ROWID 存儲在一起,從而實現了上述目標。而在位圖索引(bitmap index)中,只需存儲每個鍵值的位圖(bitmap),而非一組 ROWID。
? ? ??? 位圖(bitmap)中的每一位(bit)對應一個可能的 ROWID。如果某一位被置位(set),則表明著與此位對應的 ROWID 所指向的行中 包含此位所代表的鍵值(key value)。Oracle 通過一個映射函數(mapping function)將位信息轉化為實際的 ROWID,因此雖然位圖索引(bitmap index)內部的存儲結構與常規索引不同,但她同樣能實現常規索引的功能。當不同值的索引鍵的數量較少時,位圖索引的存儲效率相當高。
? ? ? ? 如果在?WHERE?子句內引用的多個列上都建有位圖索引(bitmap index),那么進行位圖索引掃描時(bitmap indexing)可以將各個位圖索引融合在一起。不滿足全部條件的行可以被預先過濾掉。因此使用位圖索引能夠極大地提高查詢的響應時間。
5.8.11.1 數據倉庫應用中位圖索引的優勢
? ? ? ? 數據倉庫應用(data warehousing application)的特點是數據量巨大,執行的多為自定義查詢(ad hoc query),且并發事務較少。這種環境下使用位圖索引(bitmap index)具備如下優勢:
- 能夠減少大數據量自定義查詢的響應時間
- 與其他索引技術相比能夠節省大量存儲空間
- 即使硬件配置較低也能顯著提高性能
- 有利于并行 DML 和并行加載
? ? ? ? 為一個大表建立傳統的平衡樹索引(B-tree index)可能占用極大的存儲空間,索引有可能比數據表還要大數倍。而一個位圖索引(bitmap index)所占的空間比被索引數據還要小得多。
? ? ??? 位圖索引(bitmap index)不適用于 OLTP 系統,因為這樣的系統中存在大量對數據進行修改的并發事務。位圖索引主要用于數據倉庫系統中(data warehousing)的決策支持功能,在這種環境下用戶對數據的操作主要是查詢而非修改。
? ? ? ? 主要進行大于(greater than)或小于(less than)比較的列,不適宜使用位圖索引(bitmap index)。例如,WHERE?子句中常會將 salary 列和一個值進行比較,此時更適合使用平衡樹索引(B-tree index)。位圖索引適用于等值查詢,尤其是存在?AND,OR,和?NOT?等邏輯操作符的組合時。
? ? ? ? 位圖索引(bitmap index)是集成在 Oracle 的優化器(optimizer)和執行引擎(execution engine)之中的。位圖索引也能夠和 Oracle 中的其他執行方法(execution method)無縫地組合。例如,優化器可以在利用一個表的位圖索引和另一個表的平衡樹索引(B-tree index)對這兩張表進行哈希連接(hash join)。優化器能夠在位圖索引及其他可用的訪問方法(例如常規的平衡樹索引,或全表掃描(full table scan))中選擇效率最高的方式,同時考慮是否適合使用并行執行。
? ? ? ? 位圖索引(bitmap index)如同常規索引一樣,可以結合并行查詢(parallel query)和并行 DML(parallel DML)一起工作。建立于分區表(partitioned table)的位圖索引必須為本地索引(local index)。Oracle 還支持并行地創建位圖索引,以及創建復合位圖索引。
5.8.11.2 基數
? ? ? ??在基數(cardinality)小的列上建立位圖索引(bitmap index)效果最好。所謂某列的基數小(low cardinality)是指此列中所有不相同的值的個數要小于總行數。如果某列中所有不相同的值的個數占總行數的比例小于 1%,或某列中值的重復數量在 100 個以上,那么就可以考慮在此列上建立位圖索引。即便某列的基數較上述標準稍大,或值的重復數量較上述標準稍小,如果在一個查詢的?WHERE?子句中需要引用此列定義復雜的條件,也可以考慮在此列上建立位圖索引。
? ? ? ? 例如,一個表包含一百萬行數據,其中的一列包含一萬個不相同的值,就可以考慮在此列上創建位圖索引(bitmap index)。此列上位圖索引的查詢性能將超過平衡樹索引(B-tree index),當此列與其他列作為組合條件時效果尤為明顯。
? ? ? ? 平衡樹索引(B-tree index)適用于高基數的數據,即數據的可能值很多,例如CUSTOMER_NAME?或?PHONE_NUMBER?列。在有些情況下,平衡樹索引所需的存儲空間可能比被索引數據還要大。如果使用得當,位圖索引將遠遠小于同等情況下的平衡樹索引。
? ? ? ??對于自定義查詢(ad hoc query)或相似的應用,使用位圖索引(bitmap index)能夠顯著地提高查詢性能。查詢的?WHERE?子句中的?AND?和?OR?條件直接對位圖(bitmap)進行布爾運算(Boolean operation)得到一個位圖結果集(resulting bitmap),而無需將所有的位圖轉換為 ROWID。如果布爾操作后的結果集較小,那么查詢就能夠迅速得到結果,而無需進行全表掃描(full table scan)。
5.8.11.3?位圖索引和空值
? ? ? ? 與其他大多數索引不同,位圖索引(bitmap index)可以包含鍵值(key value)為?NULL?的行。將鍵值為空的行進行索引對有些 SQL 語句是有用處的,例如包含?COUNT?聚合函數的查詢。
5.8.11.4 分區表上的位圖索引
? ? ? ? 用戶可以在分區表(partitioned table)上創建位圖索引(bitmap index)。唯一的限制是位圖索引對分區表來說必須是本地的(local),而不能是全局索引(global index)。只有非分區表才能使用全局位圖索引。
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
5.8.12 位圖連接索引
? ? ??? 除了建立在單個表之上的位圖索引(bitmap index),用戶還可以創建位圖連接索引(bitmap join index),此種索引是為了連接(join)兩個或多個數據表而建的。位圖連接索引(bitmap join index)可以預先將有連接關系的數據進行保存,且所需的存儲空間較小。對于一個表的某列的每個值,位圖連接索引為其保存其他表中與此值有連接關系的數據行的 rowid。在數據倉庫環境中,連接關系通常是維表(dimension table)中的主鍵(primary key)與事實表(fact table)中的外鍵(foreign key)進行等值內連接(equi-inner join)。
? ? ? ? 物化連接視圖(materialized join view)也是一種預先將連接物化的方法,但與之相比位圖連接索引(bitmap join index)所需的存儲空間更少。因為物化連接視圖不會壓縮事實表(fact table)中的 rowid。
https://blog.csdn.net/zdwzzu2006/article/details/8197590
?
?
?
?
?
?
原
Oracle-index索引解讀
2016年10月27日 21:25:05?小小工匠?閱讀數:6157?標簽:?oracle索引數據庫?更多
個人分類:?【數據庫-Oracle基礎】
所屬專欄:?Oralce手札
版權聲明:【show me the code ,change the world】 https://blog.csdn.net/yangshangwei/article/details/52949803
概述
Oracle-OLAP和OLTP解讀
Oracle-index索引解讀
Oracle-分區表解讀
Oracle-鎖解讀
Oracle-等待事件解讀
Oracle-procedure/cursor解讀
-
索引是數據庫對象之一,用于加快數據的檢索
-
索引是建立在表上的可選對象;索引的關鍵在于通過一組排序后的索引鍵來取代默認的全表掃描檢索方式,索引直接指向包含所查詢值的行的位置,減少磁盤I/O,,從而提高檢索效率
-
索引在邏輯上和物理上都與相關的表和數據無關,當創建或者刪除一個索引時,不會影響基本的表,與所索引的表是相互獨立的物理結構
-
索引一旦建立,Oracle 自動使用并維護索引,插入、刪除、更新表后,自動更新索引,不會對表產生影響.
-
索引對用戶是透明的,無論表上是否有索引,sql語句的用法不變
-
oracle創建主鍵時會自動在該列上創建索引
為什么需要索引
數據在磁盤上是以塊的形式存儲的。為確保對磁盤操作的原子性,訪問數據的時候會一并訪問所有數據塊。磁盤上的這些數據塊與鏈表類似,即它們都包含一個數據段和一個指針,指針指向下一個節點(數據塊)的內存地址,而且它們都不需要連續存儲(即邏輯上相鄰的數據塊在物理上可以相隔很遠)。
鑒于很多記錄只能做到按一個字段排序,所以要查詢某個未經排序的字段,就需要使用線性查找,即要訪問N/2個數據塊,其中N指的是一個表所涵蓋的所有數據塊。如果該字段是非鍵字段(也就是說,不包含唯一值),那么就要搜索整個表空間,即要訪問全部N個數據塊。
然而,對于經過排序的字段,可以使用二分查找,因此只要訪問log2 N個數據塊。同樣,對于已經排過序的非鍵字段,只要找到更大的值,也就不用再搜索表中的其他數據塊了。這樣一來,性能就會有實質性的提升。
什么是索引
索引是對記錄按照多個字段進行排序的一種方式。對表中的某個字段建立索引會創建另一種數據結構,其中保存著字段的值,每個值又指向與它相關的記錄。這種索引的數據結構是經過排序的,因而可以對其執行二分查找。
索引的缺點是占用額外的磁盤空間。所以如果為同一個表中的很多字段都建立索引,那這個文件可能會很快膨脹到文件系統規定的上限。
當對表中的數據進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了數據的維護速度。
索引的原理
首先,來看一個示例數據庫表的模式:
注意:這里用char而不用varchar是為了精確地描述數據占用磁盤的大小。
這個示例數據庫中包含500萬行記錄,而且沒有建立索引。
接下來我們就分析針對這個表的兩個查詢:一個查詢使用id(經過排序的鍵字段),另一個查詢使用firstName(未經排序的非鍵字段)。
示例分析一
對于這個擁有r = 5 000 000條記錄的示例數據庫,在磁盤上要為每條記錄分配 R = (4+50+50+100)204字節的固定存儲空間(4個字段所占空間的總和)。
默認的數據庫塊大小為 B = 1024字節。于是,我們可計算出這個表的分塊因數為 bfr = (B/R) = 1024/204 = 5,即磁盤上每個數據塊保存5條記錄。那么,保存整個表所需的數據塊數就是 N = (r/bfr) = 5000000/5 = 1 000 000。
使用線性查找搜索id字段——這個字段是鍵字段(每個字段的值唯一),需要訪問 N/2 = 500 000個數據塊才能找到目標值。不過,因為這個字段是經過排序的,所以可以使用二分查找法,而這樣平均只需要訪問log2(1000000 )= 19.93 = 20 個塊。顯然,這會給性能帶來極大的提升。
再來看看firstName字段,這個字段是未經排序的,因此不可能使用二分查找,況且這個字段的值也不是唯一的,所以要從表的開頭查找末尾,即要訪問 N = 1 000 000個數據塊。這種情況通過建立索引就能得到改善。
如果一條索引記錄只包含索引字段和一個指向原始記錄的指針,那么這條記錄肯定要比它所指向的包含更多字段的記錄更小。也就是說,索引本身占用的磁盤空間比原來的表更少,因此需要遍歷的數據塊數也比搜索原來的表更少。
以下是firstName字段索引的模式:
示例分析二
對于這個擁有r = 5 000 000條記錄的示例數據庫,每條索引記錄要占用 R = 54字節磁盤空間,而且同樣使用默認的數據塊大小 B = 1024字節。那么索引的分塊因數就是 bfr = (B/R) = 1024/54 = 18。最終這個表的索引需要占用 N = (r/bfr) = 5000000/18 = 277 778個數據塊。
現在,再搜索firstName字段就可以使用索引來提高性能了。對索引使用二分查找,需要訪問 log2 277778 = 18.09 = 19個數據塊。再加上為找到實際記錄的地址還要訪問一個數據塊,總共要訪問 19 + 1 = 20個數據塊,這與搜索未索引的表需要訪問277 778個數據塊相比,不啻于天壤之別。
什么時候用索引
創建索引要額外占用磁盤空間(比如,上面例子中要額外占用277 778個數據塊),建立的索引太多可能導致磁盤空間不足。因此,在建立索引時,一定要慎重選擇正確的字段。
由于索引只能提高搜索記錄中某個匹配字段的速度,因此在執行插入和刪除操作的情況下,僅為輸出結果而為字段建立索引,就純粹是浪費磁盤空間和處理時間了;這種情況下不用建立索引。
另外,由于二分查找的原因,數據的基數性(cardinality)或唯一性也非常重要。對基數性為2的字段建立索引,會將數據一分為二,而對基數性為1000的字段,則同樣會返回大約1000條記錄。在這么低的基數性下,索引的效率將減低至線性查找的水平,而查詢優化器會在基數性小于記錄數的30%時放棄索引,實際上等于索引純粹只會浪費空間。
另外需要說明:?創建了索引并不一定就會使用,oracle自動統計表的信息后,決定是否使用索引,表中數據很少時使用全表掃描速度已經很快,沒有必要使用索引
索引的語法
創建索引
<span style="color:#000000"><code>CREATE UNIUQE | BITMAP INDEX <span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>schema</strong></span>></span>.<span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>index_name</strong></span>></span>ON <span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>schema</strong></span>></span>.<span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>table_name</strong></span>></span>(<span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>column_name</strong></span>></span> | <span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>expression</strong></span>></span> ASC | DESC,<span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>column_name</strong></span>></span> | <span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>expression</strong></span>></span> ASC | DESC,...)TABLESPACE <span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>tablespace_name</strong></span>></span>STORAGE <span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>storage_settings</strong></span>></span>LOGGING | NOLOGGINGCOMPUTE STATISTICSNOCOMPRESS | COMPRESS<span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>nn</strong></span>></span>NOSORT | REVERSEPARTITION | GLOBAL PARTITION<span style="color:#006666 !important"><<span style="color:#4f4f4f !important"><strong>partition_setting</strong></span>></span></code></span>- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
參數說明:
-
1) UNIQUE | BITMAP:指定UNIQUE為唯一值索引,BITMAP為位圖索引,省略為B-Tree索引。
-
2)<column_name> | <expression> ASC |?
DESC:可以對多列進行聯合索引,當為expression時即“基于函數的索引” -
3)TABLESPACE:指定存放索引的表空間(索引和原表不在一個表空間時效率更高)
-
4)STORAGE:可進一步設置表空間的存儲參數
-
5)LOGGING | NOLOGGING:是否對索引產生重做日志(對大表盡量使用NOLOGGING來減少占用空間并提高效率)
-
6)COMPUTE STATISTICS:創建新索引時收集統計信息
-
7)NOCOMPRESS | COMPRESS<nn>:是否使用“鍵壓縮”(使用鍵壓縮可以刪除一個鍵列中出現的重復值)
-
8)NOSORT | REVERSE:NOSORT表示與表中相同的順序創建索引,REVERSE表示相反順序存儲索引值
-
9)PARTITION | NOPARTITION:可以在分區表和未分區表上對創建的索引進行分區
修改索引
重命名索引
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>alter</strong></span> index index_sno rename <span style="color:#000088 !important"><strong>to</strong></span> bitmap_index;</code></span>- 1
合并索引
表使用一段時間后在索引中會產生碎片,此時索引效率會降低,可以選擇重建索引或者合并索引,合并索引方式更好些,無需額外存儲空間,代價較低
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>alter</strong></span> index index_sno coalesce;</code></span>- 1
重建索引
方式一:刪除原來的索引,重新建立索引
方式二:使用rebuild方式
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>alter</strong></span> index index_sno rebuild [online];</code></span>- 1
rebuild 和 rebuild online的區別
alter index rebuild online:實質上是掃描表而不是掃描現有的索引塊來實現索引的重建
alter index rebuild:只掃描現有的索引塊來實現索引的重建。
rebuild index online在執行期間不會阻塞DML操作,但在開始和結束階段,需要請求模式為4的TM鎖。因此,如果在rebuild index online開始前或結束時,有其它長時間的事物在運行,很有可能就造成大量的鎖等待。也就是說在執行前仍會產生阻塞, 應該避免排他鎖.
而rebuild index在執行期間會阻塞DML操作, 但速度較快.
兩者重建索引時的掃描方式不同,?
rebuild用的是“INDEX FAST FULL SCAN”,?
rebuild online用的是“TABLE ACCESS FULL”;?
即rebuild index是掃描索引塊,而rebuild index online是掃描全表的數據塊.
刪除索引
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>drop</strong></span> index index_sno;</code></span>- 1
查看索引
<span style="color:#000000"><code>查詢all_indexes <span style="color:#000088 !important"><strong>select</strong></span> index_name, index_type, tablespace_name, uniqueness<span style="color:#000088 !important"><strong>from</strong></span> all_indexes<span style="color:#000088 !important"><strong>where</strong></span> table_name = <span style="color:#009900 !important">'tablename'</span>;或者查詢user_indexes <span style="color:#000088 !important"><strong>select</strong></span> a.* <span style="color:#000088 !important"><strong>from</strong></span> user_indexes a ;</code></span>- 1
- 2
- 3
- 4
- 5
- 6
- 7
B樹索引的index_type為 NORMAL;而位圖索引的index_type類型值為BITMAP
索引分類
- B-樹索引(默認類型)
- 位圖索引
- HASH索引
- 索引編排表
- 反轉鍵索引
- 基于函數的索引
- 分區索引
- 本地和全局索引
B樹索引
說明
B樹索引在Oracle中是一個通用索引。在創建索引時它就是默認的索引類型。B樹索引可以是一個列的(簡單)索引,也可以是組合/復合(多個列)的索引。
B樹索引最多可以包括32列。
特點
1.oracle中最常用的索引;B樹索引就是一顆二叉樹;葉子節點(雙向鏈表)包含索引列和指向表中每個匹配行的ROWID值
2.所有葉子節點具有相同的深度,因而不管查詢條件怎樣,查詢速度基本相同
3.能夠適應精確查詢、模糊查詢和比較查詢
創建
B樹索引的單一索引
單一索引:
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>Create</strong></span> <span style="color:#000088 !important"><strong>Index</strong></span> <<span style="color:#000088 !important"><strong>Index</strong></span>-Name> <span style="color:#000088 !important"><strong>On</strong></span> <Table_Name>(Column_Name)</code></span>- 1
B樹索引的 復合索引
復合索引:
<span style="color:#000000"><code> <span style="color:#000088 !important"><strong>Create</strong></span> <span style="color:#000088 !important"><strong>Index</strong></span> i_deptno_job <span style="color:#000088 !important"><strong>on</strong></span> emp(deptno,job); —>在emp表的deptno、job列建立索引。</code></span>- 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
如果在where 子句中有OR 操作符或單獨引用Job 列(索引列的后面列) 則將不會走索引,將會進行全表掃描。?
?
即如果索引建立在多個列上,只有它的第一個列被where子句引用時,優化器才會使用該索引,即至少要包含組合索引的第一列
適合使用場景
- 適合與大量的增、刪、改(OLTP)
- 不能用包含OR操作符的查詢;
- 列基數(列不重復值的個數)大時適合使用B數索引
位圖索引
說明
創建位圖索引時,oracle會掃描整張表,并為索引列的每個取值建立一個位圖(位圖中,對表中每一行使用一位(bit,0或者1)來標識該行是否包含該位圖的索引列的取值,如果為1,表示對應的rowid所在的記錄包含該位圖索引列值),最后通過位圖索引中的映射函數完成位到行的ROWID的轉換.
位圖索引非常適合于決策支持系統(Decision Support System,DSS)和數據倉庫,它們不應該用于通過事務處理應用程序訪問的表。
它們可以使用較少到中等基數(不同值的數量)的列訪問非常大的表。?
盡管位圖索引最多可達30個列,但通常它們都只用于少量的列。
比如:某個表可能包含一個稱為Sex的列,它有兩個可能值:男和女。這個基數只為2,如果用戶頻繁地根據Sex列的值查詢該表,這就是位圖索引的基列。當一個表內包含了多個位圖索引時,您可以體會到位圖索引的真正威力。如果有多個可用的位圖索引,Oracle就可以合并從每個位圖索引得到的結果集,快速刪除不必要的數據。
特點
- 適合與決策支持系統;
- 做UPDATE代價非常高;
- 非常適合OR操作符的查詢;
- 基數比較少的時候才能建位圖索引;
創建
例子:
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>Create</strong></span> bitmap <span style="color:#000088 !important"><strong>Index</strong></span> <<span style="color:#000088 !important"><strong>Index</strong></span>-Name> <span style="color:#000088 !important"><strong>On</strong></span> <Table_Name>(Column_Name)</code></span>- 1
適合使用場景
- 對于基數小的列適合建立位圖索引(例如性別等)
注意事項
-
建議不要在一些聯機事務處理(OLTP)應用程序中使用位圖索引。位圖索引的索引值中包含ROWID,這樣Oracle就可以在行級別上鎖定索引。
位圖索引存儲為壓縮的索引值,其中包含了一定范圍的ROWID,因此Oracle必須針對一個給定值鎖定所有范圍內的ROWID。這種鎖定類型可能在某些DML語句中造成死鎖。
SELECT語句不會受到這種鎖定問題的影響。
-
基于規則的優化器不會考慮位圖索引。
- 當執行ALTER TABLE語句并修改包含有位圖索引的列時,會使位圖索引失效。
- 位圖索引不包含任何列數據,并且不能用于任何類型的完整性檢查。
- 位圖索引不能被聲明為唯一索引。
- 位圖索引的最大長度為30。
函數索引
說明
-
當經常要訪問一些函數或者表達式時,可以將其存儲在索引中,這樣下次訪問時,該值已經計算出來了,可以加快查詢速度
-
函數索引既可以使用B樹索引,也可以使用位圖索引;當函數結果不確定時采用B樹索引,結果是固定的某幾個值時使用位圖索引
-
函數索引中可以使用len、trim、substr、upper(每行返回獨立結果),不能使用如sum、max、min、avg等
-
基于函數的索引非常有用,但在實現時必須小心。在表上創建的索引越多,INSERT、UPDATE和DELETE語句的執行就會花費越多的時間。
創建
例子:
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>CREATE</strong></span> <span style="color:#000088 !important"><strong>INDEX</strong></span> <span style="color:#000088 !important"><strong>index</strong></span> <span style="color:#000088 !important"><strong>ON</strong></span> table (<span style="color:#ff79c6"><strong>FUNCTION</strong></span><span style="color:#4f4f4f !important">(column)</span>);舉例: <span style="color:#000088 !important"><strong>select</strong></span> * <span style="color:#000088 !important"><strong>from</strong></span> student <span style="color:#000088 !important"><strong>where</strong></span> upper(name) =<span style="color:#009900 !important">'XGJ'</span>;</code></span>- 1
- 2
- 3
- 4
分區索引
分區索引就是簡單地把一個索引分成多個片斷。通過把一個索引分成多個片斷,可以訪問更小的片斷(也更快),并且可以把這些片斷分別存放在不同的磁盤驅動器上(避免I/O問題)。
B樹和位圖索引都可以被分區,而HASH索引不可以被分區。
可以有好幾種分區方法:表被分區而索引未被分區;表未被分區而索引被分區;表和索引都被分區。
不管采用哪種方法,都必須使用基于成本的優化器。分區能夠提供更多可以提高性能和可維護性的可能性
有兩種類型的分區索引:本地分區索引和全局分區索引。
每個類型都有兩個子類型,有前綴索引和無前綴索引。表各列上的索引可以有各種類型索引的組合。如果使用了位圖索引,就必須是本地索引。
把索引分區最主要的原因是可以減少所需讀取的索引的大小,另外把分區放在不同的表空間中可以提高分區的可用性和可靠性。
在使用分區后的表和索引時,Oracle還支持并行查詢和并行DML。這樣就可以同時執行多個進程,從而加快處理這條語句。
創建索引的一些規則
1. 權衡索引個數與DML之間關系,DML也就是插入、刪除數據操作。?
這里需要權衡一個問題,建立索引的目的是為了提高查詢效率的,但建立的索引過多,會影響插入、刪除數據的速度,因為我們修改的表數據,索引也要跟著修改。這里需要權衡我們的操作是查詢多還是修改多。
2. 把索引與對應的表放在不同的表空間。?
當讀取一個表時表與索引是同時進行的。如果表與索引和在一個表空間里就會產生資源競爭,放在兩個表這空就可并行執行。
3. 最好使用一樣大小的塊。?
Oracle默認五塊,讀一次I/O,如果你定義6個塊或10個塊都需要讀取兩次I/O。最好是5的整數倍更能提高效率。
4. 如果一個表很大,建立索引的時間很長,因為建立索引也會產生大量的redo信息,所以在創建索引時可以設置不產生或少產生redo信息。只要表數據存在,索引失敗了大不了再建,所以可以不需要產生redo信息。
5. 建索引的時候應該根據具體的業務SQL來創建,特別是where條件,還有where條件的順序,盡量將過濾大范圍的放在后面,因為SQL執行是從后往前的。
索引應該經常建在Where 子句經常用到的列上。如果某個大表經常使用某個字段進行查詢,并且檢索行數小于總表行數的5%。則應該考慮。
6. 如果有兩個或者以上的索引,其中有一個唯一性索引,而其他是非唯一,這種情況下oracle將使用唯一性索引而完全忽略非唯一性索引
7. 至少要包含組合索引的第一列(即如果索引建立在多個列上,只有它的第一個列被where子句引用時,優化器才會使用該索引)
8. 小表不要建立索引
9. 對于基數大的列適合建立B樹索引,對于基數小的列適合建立位圖索引
10. 列中有很多空值,但經常查詢該列上非空記錄時應該建立索引
11. 經常進行連接查詢的列應該創建索引
12. 使用create index時要將最常查詢的列放在最前面
13. LONG(可變長字符串數據,最長2G)和LONG RAW(可變長二進制數據,最長2G)列不能創建索引
14. 限制表中索引的數量(創建索引耗費時間,并且隨數據量的增大而增大;索引會占用物理空間;當對表中的數據進行增加、刪除和修改的時候,索引也要動態的維護,降低了數據的維護速度)
15 .對于兩表連接的字段,應該建立索引。如果經常在某表的一個字段進行Order By 則也應該建立索引。
索引失效的情況
1.使用不等于操作符(not 、<>、!=)
oracle碰到not或者 <> !=會停止使用索引,而采用全表掃描
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>select</strong></span> * <span style="color:#000088 !important"><strong>from</strong></span> student <span style="color:#000088 !important"><strong>where</strong></span> <span style="color:#000088 !important"><strong>not</strong></span> (score=<span style="color:#006666 !important">100</span>);<span style="color:#000088 !important"><strong>select</strong></span> * <span style="color:#000088 !important"><strong>from</strong></span> student <span style="color:#000088 !important"><strong>where</strong></span> score <> <span style="color:#006666 !important">100</span>;<span style="color:#880000 !important">--替換為</span><span style="color:#000088 !important"><strong>select</strong></span> * <span style="color:#000088 !important"><strong>from</strong></span> student <span style="color:#000088 !important"><strong>where</strong></span> score><span style="color:#006666 !important">100</span> <span style="color:#000088 !important"><strong>or</strong></span> score <<span style="color:#006666 !important">100</span></code></span>- 1
- 2
- 3
- 4
- 5
- 6
- 7
通過把不等于操作符改成OR條件,就可以使用索引,以避免全表掃描。
2. 使用IS NULL 或IS NOT NULL
使用IS NULL 或IS NOT NULL同樣會限制索引的使用。?
因為NULL值并沒有被定義。在SQL語句中使用NULL會有很多的麻煩。因此建議開發人員在建表時,把需要索引的列設成 NOT NULL。?
如果被索引的列在某些行中存在NULL值,就不會使用這個索引(除非索引是一個位圖索引)。
- 1
索引上使用空值比較將停止使用索引.
3.使用函數
如果不使用基于函數的索引,那么在SQL語句的WHERE子句中對存在索引的列使用函數時,會使優化器忽略掉這些索引。 下面的查詢不會使用索引(只要它不是基于函數的索引)
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>select</strong></span> empno,ename,deptno <span style="color:#000088 !important"><strong>from</strong></span> emp <span style="color:#000088 !important"><strong>where</strong></span> trunc(hiredate)=<span style="color:#009900 !important">'01-MAY-81'</span>;<span style="color:#880000 !important">--把上面的語句改成下面的語句,這樣就可以通過索引進行查找。</span> <span style="color:#000088 !important"><strong>select</strong></span> empno,ename,deptno <span style="color:#000088 !important"><strong>from</strong></span> emp <span style="color:#000088 !important"><strong>where</strong></span> hiredate<(to_date(<span style="color:#009900 !important">'01-MAY-81'</span>)+<span style="color:#006666 !important">0.9999</span>);</code></span>- 1
- 2
- 3
- 4
4.索引列上進行計算
索引列上不能進行計算
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>SELECT</strong></span> Col <span style="color:#000088 !important"><strong>FROM</strong></span> tbl <span style="color:#000088 !important"><strong>WHERE</strong></span> col / <span style="color:#006666 !important">10</span> > <span style="color:#006666 !important">10</span></code></span>- 1
則會使索引失效,應該改成
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>SELECT</strong></span> Col <span style="color:#000088 !important"><strong>FROM</strong></span> tbl <span style="color:#000088 !important"><strong>WHERE</strong></span> col > <span style="color:#006666 !important">10</span> * <span style="color:#006666 !important">10</span></code></span>- 1
5.比較不匹配的數據類型
假設account_number是一個VARCHAR2類型,在account_number字段上有索引。?
下面的語句將執行全表掃描:
- 1
Oracle可以自動把where子句變成to_number(account_number)=990354,這樣就限制了索引的使用。
改成下面的查詢就可以使用索引:
<span style="color:#000000"><code> <span style="color:#000088 !important"><strong>select</strong></span> bank_name,address,city,state,zip <span style="color:#000088 !important"><strong>from</strong></span> banks <span style="color:#000088 !important"><strong>where</strong></span> account_number =<span style="color:#009900 !important">'990354'</span>;</code></span>- 1
特別注意:不匹配的數據類型之間比較會讓Oracle自動限制索引的使用,即便對這個查詢執行Explain Plan也不能讓您明白為什么做了一次“全表掃描”。
6.通配符在搜索詞首出現時,oracle不能使用索引
<span style="color:#000000"><code><span style="color:#880000 !important">--我們在name上創建索引;</span><span style="color:#000088 !important"><strong>create</strong></span> index index_name <span style="color:#000088 !important"><strong>on</strong></span> student(<span style="color:#009900 !important">'name'</span>);<span style="color:#880000 !important">--下面的方式oracle不適用name索引</span><span style="color:#000088 !important"><strong>select</strong></span> * <span style="color:#000088 !important"><strong>from</strong></span> student <span style="color:#000088 !important"><strong>where</strong></span> name <span style="color:#000088 !important"><strong>like</strong></span> <span style="color:#009900 !important">'%xgj%'</span>;<span style="color:#880000 !important">--如果通配符出現在字符串的其他位置時,優化器能夠利用索引;如下:</span><span style="color:#000088 !important"><strong>select</strong></span> * <span style="color:#000088 !important"><strong>from</strong></span> student <span style="color:#000088 !important"><strong>where</strong></span> name <span style="color:#000088 !important"><strong>like</strong></span> <span style="color:#009900 !important">'xgj%'</span>;</code></span>- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
7.用UNION替換OR(適用于索引列)
union:是將兩個查詢的結果集進行追加在一起,它不會引起列的變化。
由于是追加操作,需要兩個結果集的列數應該是相關的,并且相應列的數據類型也應該相當的。
union 返回兩個結果集,同時將兩個結果集重復的項進行消除。
如果不進行消除,用UNOIN ALL.
通常情況下, 用UNION替換WHERE子句中的OR將會起到較好的效果. 對索引列使用OR將造成全表掃描.?注意, 以上規則只針對多個索引列有效.
如果有column沒有被索引, 查詢效率可能會因為你沒有選擇OR而降低.
在下面的例子中, LOC_ID 和REGION上都建有索引.
高效:
<span style="color:#000000"><code> <span style="color:#000088 !important"><strong>SELECT</strong></span> LOC_ID , LOC_DESC , REGION<span style="color:#000088 !important"><strong>FROM</strong></span> LOCATION<span style="color:#000088 !important"><strong>WHERE</strong></span> LOC_ID = <span style="color:#006666 !important">10</span><span style="color:#000088 !important"><strong>UNION</strong></span><span style="color:#000088 !important"><strong>SELECT</strong></span> LOC_ID , LOC_DESC , REGION<span style="color:#000088 !important"><strong>FROM</strong></span> LOCATION<span style="color:#000088 !important"><strong>WHERE</strong></span> REGION = “MELBOURNE”</code></span>- 1
- 2
- 3
- 4
- 5
- 6
- 7
低效:?
- 1
- 2
- 3
如果你堅持要用OR, 那就需要返回記錄最少的索引列寫在最前面.
8. 用EXISTS替代IN、用NOT EXISTS替代NOT IN
在許多基于基礎表的查詢中, 為了滿足一個條件, 往往需要對另一個表進行聯接. 在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率.
在子查詢中, NOT IN子句將執行一個內部的排序和合并.
無論在哪種情況下, NOT IN都是最低效的(因為它對子查詢中的表執行了一個全表遍歷).
為了避免使用NOT IN, 我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS.
例子:
高效:
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>SELECT</strong></span> * <span style="color:#000088 !important"><strong>FROM</strong></span> EMP (基礎表) <span style="color:#000088 !important"><strong>WHERE</strong></span> EMPNO > <span style="color:#006666 !important">0</span> <span style="color:#000088 !important"><strong>AND</strong></span> <span style="color:#000088 !important"><strong>EXISTS</strong></span> (<span style="color:#000088 !important"><strong>SELECT</strong></span> ‘X’ <span style="color:#000088 !important"><strong>FROM</strong></span> DEPT <span style="color:#000088 !important"><strong>WHERE</strong></span> DEPT.DEPTNO = EMP.DEPTNO <span style="color:#000088 !important"><strong>AND</strong></span> LOC = ‘MELB’)</code></span>- 1
低效:
<span style="color:#000000"><code><span style="color:#000088 !important"><strong>SELECT</strong></span> * <span style="color:#000088 !important"><strong>FROM</strong></span> EMP (基礎表) <span style="color:#000088 !important"><strong>WHERE</strong></span> EMPNO > <span style="color:#006666 !important">0</span> <span style="color:#000088 !important"><strong>AND</strong></span> DEPTNO <span style="color:#000088 !important"><strong>IN</strong></span>(<span style="color:#000088 !important"><strong>SELECT</strong></span> DEPTNO <span style="color:#000088 !important"><strong>FROM</strong></span> DEPT <span style="color:#000088 !important"><strong>WHERE</strong></span> LOC = ‘MELB’)</code></span>- 1
Sql優化的一點建議
Sql 優化:
當Oracle數據庫拿到SQL語句時,其會根據查詢優化器分析該語句,并根據分析結果生成查詢執行計劃。?
也就是說,數據庫是執行的查詢計劃,而不是Sql語句。
查詢優化器有rule-based-optimizer(基于規則的查詢優化器) 和Cost-Based-optimizer(基于成本的查詢優化器)。
其中基于規則的查詢優化器在10g版本中消失。
對于規則查詢,其最后查詢的是全表掃描。而CBO則會根據統計信息進行最后的選擇。
-
1、先執行From ->Where ->Group By->Order By
-
2、執行From 字句是從右往左進行執行。因此必須選擇記錄條數最少的表放在右邊。
-
3、對于Where字句其執行順序是從后向前執行、因此可以過濾最大數量記錄的條件必須寫在Where子句的末尾,而對于多表之間的連接,則寫在之前。?
因為這樣進行連接時,可以去掉大多不重復的項。 -
4、SELECT子句中避免使用(*)ORACLE在解析的過程中, 會將’*’ 依次轉換成所有的列名, 這個工作是通過查詢數據字典完成的,這意味著將耗費更多的時間
https://blog.csdn.net/yangshangwei/article/details/52949803
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的Oracle 数据库 各种索引类型 简单介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 训练集,验证集,测试集
- 下一篇: 学生体温打卡系统Java+MySQL