@[toc]
數據庫非常強大,如果您的數據庫性能較低或執行SQL語句的效率很低,最主要原因應該是索引設計不合理或使用索引不合理。
所謂的SQL優化,主要的內容就是如何設計索引和如何利用索引。
一、索引的概念
如果一本書只有幾頁,讀者隨便翻翻就能很快的找到具體的內容,根本不需要目錄,如果一本書有幾百頁、幾千頁,沒有目錄,查找內容的將需要更長的時間,書越厚,耗時越長。
索引,即表的索引,它對表的重要性就像目錄對書一樣重要,索引可以大幅提升數據查找的效率。
1、索引的特點
1)索引是表的一部分,是可選的,表可以沒有索引,就像書可以沒有目錄一樣,數據庫不做強制要求。
2)合理的索引可以提高數據查找的效率,減少磁盤I/O。
3)唯一索引可以約束表數據的完整性。
4)索引也是數據,需要存儲空間。
5)數據庫自動維護索引的內容,當對表的記錄進行了增、刪、改的操作時,數據庫會自動更新索引。
6)索引雖然可以提高數據查找的效率,但對表進行增、刪、改操作時,數據庫除了維護表中的數據,還要維護索引,所以,索引會讓增、刪、改操作的效率下降。
7)索引提升了數據查找的效率,降低了數據操作的效率,在設計表和索引的時候,要根據實際情況在兩者之間權衡。
2、索引的分類
索引可分為普通索引、唯一索引、反向鍵索引、位圖索引和基于函數的索引,常用的是普通索引和唯一索引,其它三種極少使用,我也不建議使用。
本文只介紹普通索引和唯一索引。
二、創建索引
我們先來創建超女基本信息表。
create table T_GIRL
(
id char(4) not null, -- 編號
name varchar2(30) not null, -- 姓名
yz varchar2(20) null, -- 顏值
sc varchar2(20) null, -- 身材
weight number(4,1) not null, -- 體重
height number(3) not null, -- 身高

birthday date not null, -- 出生時間
memo varchar2(1000) null, -- 備注
keyid number(8) not null -- 記錄編號,從序列SEQ_GIRL中獲取。
);
alter table T_GIRL add constraint PK_GIRL primary key(id);
1、普通索引
創建普通索引的語法如下:
create index 索引名 on 表名(字段名1,字段名2,......,字段名n);
索引名是標識符,從語法上來說,索引名只要符合的規定就行了,但是,在實際開發中,我會以IDX_打頭,加表名和索引編號,例如超女基本信息表的索引,命名將會是、、、。
例如為超女信息表的姓名字段創建索引:
create index IDX_GIRL_1 on T_GIRL(name);
例如為超女信息表的顏值和身材兩個字段創建索引:
create index IDX_GIRL_2 on T_GIRL(yz,sc);
2、唯一索引
如果表中的列沒有重復的值,是唯一的,就可以創建唯一索引,唯一索引的效率比普通索引要高很多。
創建普通索引的語法如下:
create unique index 索引名 on 表名(字段名1,字段名2,......,字段名n);
例如超女基本信息表的keyid字段,其值是從序列中獲取的,肯定是個唯一的值,可以創建唯一索引。
create unique index IDX_GIRL_3 on T_GIRL(keyid);
3、主建是唯一索引
不要為表的主建創建索引,因為自動為表的主建字段創建唯一索引。
三、刪除索引
當表被刪除時,表的索引會被自動刪除,也可以采用drop index命令刪除索引。
語法:
drop index 索引名;
例如:
drop index IDX_GIRL_1;
drop index IDX_GIRL_2;
drop index IDX_GIRL_3;
注意,drop index無法刪除用于強制唯一/主鍵的索引,刪除主鍵要用以下語句:
alter table 表名 drop constraint 主鍵名;
例如:
alter table T_GIRL drop constraint PK_GIRL;
四、修改索引
修改索引的操作比較多,這些的工作一般由管理員(DBA)來執行。
1、重建索引
重建索引可以減少硬盤碎片和提高數據庫系統的性能。
語法:
alter index 索引名 rebuild;

示例:
alter index IDX_GIRL_1 rebuild;
2、整理碎片
對索引的無用空間進行合并,減少硬盤碎片和提高數據庫系統的性能。
語法:
alter index 索引名 coalesce;
示例:
alter index IDX_GIRL_1 coalesce;
3、修改索引名
語法:
alter index 索引名 rename to 新索引名;
示例:
alter index IDX_GIRL_1 rename to IDX_GIRL_NAME;
4、禁用索引
語法:
alter index 索引名 unusable;
示例:
alter index IDX_GIRL_1 unusable;

索引被禁用后,如果要啟用,需要用重建。
五、索引的存儲空間
每個數據庫用戶有一個缺省表空間,創建的表、主鍵和索引存放在缺省表空間中,也可以指定其它的表空間。
在實際應用中,會把表和索引的存儲空間分開到不同的表空間,減少磁盤的競爭,提升I/O的性能。
1、查看當前用戶的缺省表空間
從數據字典中可以查看當前用戶的缺省表空間。
2、指定索引的表空間
指定索引的表空間的語法如下:
create index 索引名 ...... tablespace 表空間名;
示例:
create unique index IDX_GIRL_3 on T_GIRL(keyid) tablespace INDEXS;
索引還有其它與存儲相關的選項,但應用場景比較少oracle用戶默認表空間,本文就不介紹了。
六、索引的優化
索引的優化體現在SQL語句的where條件中,如果where條件中的字段列表沒有創建索引,SQL語句的性能將會很低。
在設計索引的時候,必須考慮在常用的where條件,在編寫SQL語句的時候,也必須清楚表上創建了哪些索引。
1、索引的查看
在PL/SQL 軟件中可以查看表的索引。
2、SQL語句的執行計劃
利用PL/SQL 軟件可以查看SQL語句詳細的執行計劃。
3、SQL語句的執行步驟
SQL語句的執行順序是從未級節點往根級節點看的,上圖中的SQL語句執行的順序如下:
INDEX RANGE SCAN->TABLE BY INDEX ROWID-> ,GOAL=
4、執行計劃的含義
在執行計劃中,我們重點關注訪問表(TABLE BY …… )的方式,常見的有三種:
1)TABLE BY USER ROWID(通過ROWID的表存?。?/p>
rowid的值是行的物理位置,通過rowid可以快速定位到目標數據上,這也是中存取單行數據最快的方法。
示例:
2) TABLE FULL(全表掃描)
讀取表中全部的行,并檢查每一行是否滿足SQL語句中where的條件。
示例:
數據量太大的表不能使用全表掃描,除非本身需要取出的數據較多,占到表數據總量的5%\~10% 或以上。
全表掃描會讓數據庫的性能大幅下降,程序員一定要避免這種情況的發生,除非您知道自己在做什么。
3) TABLE BY INDEX SCAN(索引掃描)
在索引中,存儲了每個索引的鍵值和行的rowid,所以索引掃描其實是先掃描索引得到對應的rowid,然后再通過rowid定位到具體的行。
示例:
索引掃描又分五種:
a)INDEX SCAN,索引唯一掃描,效率最高。
b)INDEX RANGE SCAN,索引范圍掃描,效率較高。
c)INDEX FULL SCAN,索引全掃描,效率較低。
d)INDEX FAST FULL SCANoracle用戶默認表空間,索引快速掃描,效率一般。
e)INDEX SKIP SCAN,索引跳躍掃描,效率還行。
在 name中顯示了SQL語句使用的索引名,是索引優化的重要依據。