一、什麼是索引
百度百科: 在oracle索引是一種供服務器在表中快速查找一個行的數據庫結構。合理使用索引能夠大大提高數據庫的運行效率。
個人解讀:
1、索引是與表相關的一個可選結構,表中可以存在索引,也可以不存在索引。
2、在邏輯上和物理上都獨立於表,索引和表可以存放在不同的表空間下面(邏輯上分離),可以存放在不同的磁盤下面(物理上分離)。
3、索引用於快速查找表的內容,可以提高SQL性能。
二、索引的類型
B-Tree索引(平衡樹索引)
B-Tree索引適合於數據重複低的字段,常用於主鍵 唯一約束
Bitmap索引(位圖索引)
適用於列的基數很少、數據重複多、更新少的
text索引(全文索引)
當字段裏存儲的都是文本時適合用全文索引,常用於搜索文字
三、索引的創建
1、唯一索引:鍵值不重複
CREATE UNIQUE INDEX index_name ON table_name (column_name)
2、一般索引:鍵值可重複
CREATE INDEX index_name ON table_name (column_name)
3、複合索引:綁定了多個列
CREATE INDEX index_name ON table_name (column_name1,column_name2)
四、數據庫優化
1、SQL使用索引的例子
INDEX_COLUMN = ?
INDEX_COLUMN > ?
INDEX_COLUMN >= ?
INDEX_COLUMN < ?
INDEX_COLUMN <= ?
INDEX_COLUMN between ? and ?
INDEX_COLUMN in (?,?,...,?)
INDEX_COLUMN like ?||'%'(後導模糊查詢)
T1. INDEX_COLUMN=T2. COLUMN1(兩個表通過索引字段關聯)
2、SQL不使用索引的例子
//不等於操作不能使用索引
INDEX_COLUMN <> ?
INDEX_COLUMN not in (?,?,...,?)
//經過普通運算或函數運算後的索引字段不能使用索引
function(INDEX_COLUMN) = ?
INDEX_COLUMN + 1 = ?
INDEX_COLUMN || 'a' = ?
//含前導模糊查詢的Like語法不能使用索引
INDEX_COLUMN like '%'||?
INDEX_COLUMN like '%'||?||'%'
//B-TREE索引裏不保存字段爲NULL值記錄,因此IS NULL不能使用索引
INDEX_COLUMN is null
//Oracle在做數值比較時需要將兩邊的數據轉換成同一種數據類型,如果兩邊數據類型不同時會對字段值隱式轉換,相當於加了一層函數處理,所以不能使用索引。
NUMBER_INDEX_COLUMN='12345'
CHAR_INDEX_COLUMN=12345
a.INDEX_COLUMN=a.COLUMN_1
3、常用優化方法
注意where字句中的連接順序
ORACLE採用自下而上的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾.
尤其是“主鍵ID=?”這樣的條件。
SELECT子句中避免使用 ‘ * ‘
ORCLE在解釋的過程中,會將*依次轉換爲所有的列名,這個工作是通過查詢數據字典來完成的, 這意味着將耗費更多的時間。
避免在索引列上使用NOT
我們要避免在索引列上使用NOT, NOT會產生在和在索引列上使用函數相同的影響. 當ORACLE”遇到”NOT,他就會停止使用索引轉而執行全表掃描。
避免在索引列上使用計算
WHERE子句中,如果索引列是函數的一部分.優化器將不使用索引而使用全表掃描。
避免在索引列上使用IS NULL和IS NOT NULL
避免在索引中使用任何可以爲空的列,ORACLE性能上將無法使用該索引。對於單列索引,如果列包含空值,索引中將不存在此記錄。對於複合索引,如果每個列都爲空,索引中同樣不存在此記錄。
注意通配符%的影響
含前導模糊查詢的Like語法不能使用索引,如:
INDEX_COLUMN like ‘%’||?
後導模糊查詢的Like語法可以使用索引,如:
INDEX_COLUMN like ?||’%’
避免改變索引列的類型
Oracle在做數值比較時需要將兩邊的數據轉換成同一種數據類型,如果兩邊數據類型不同時會對字段值隱式轉換,相當於加了一層函數處理,導致不能使用索引。
用(UNION)UNION ALL替換OR (適用於索引列)
通常情況下, 用UNION替換WHERE子句中的OR將會起到較好的效果。對索引列使用OR將造成全表掃描。注意,以上規則只針對多個索引列有效。如果有column沒有被索引,查詢效率可能會因爲你沒有選擇OR而降低。
用UNION-ALL 替換UNION ( 如果有可能的話)
當 SQL語句需要UNION兩個查詢結果集合時,這兩個結果集合會以UNION-ALL的方式被合併, 然後在輸出最終結果前進行排序。 如果用UNION ALL替代UNION, 這樣排序就不是必要了, 效率就會因此得到提高。 需要注意的是,UNION ALL 將重複輸出兩個結果集合中相同記錄。
Exists替換DISTINCT
帶有DISTINCT,UNION,MINUS,INTERSECT的SQL語句會啓動SQL引擎 執行耗費資源的排序(SORT)功能。DISTINCT需要一次排序操作, 而其他的至少需要執行兩次排序。 通常, 帶有UNION,MINUS ,INTERSECT的SQL語句都可以用其他方式重寫。
合理的使用Exists和In
EXISTS:首先檢查主查詢,然後運行子查詢直到它找到第一個匹配項,這就節省了時間。
IN子查詢時:首先系統先將主查詢掛起,然後執行子查詢,並將獲得的結果列表存放在一個加了索引的臨時表中。待子查詢執行完畢,再執行主查詢。這也就是使用EXISTS比使用IN通常查詢速度快的原因。
1) select * from T1 where exists(select t1.id from T2 where T1.id=T2.id) ;
2) select * from T1 where T1.id in (select T2.id from T2) ;
T1數據量小而T2數據量非常大時,T1<<T2 時,1) 的查詢效率高。
T1數據量非常大而T2數據量小時,T1>>T2 時,2) 的查詢效率高。