索引
索引提供指針以指向存儲在表中指定的數據,就好比一本字典中的目錄,無需翻閱整本字典,利用目錄就可以快速的定位查找到所需信息。使用索引可以大大提高數據庫查詢的速度。
索引的分類
sqlserver中有多種索引類型。
按存儲結構區分:“聚集索引”,“非聚集索引”。
按數據唯一性區分:“唯一索引”,“非唯一索引”。
按鍵列個數區分:“單一索引”,“復合索引”。
- sqlserver默認情況下建立的索引是非聚集索引
類型 | 描述 |
---|---|
聚集索引 | 將表中的數據在物理上按序重新排列,因為排序只有一種排法,所以一個表只能建立一個聚集索引。 這就好比所有的漢字,我們按照拼音順序只能生產一種字典,我們按照拼音順序排列成字典。然后當我們想查找 張 字時,自然而然會翻到字典的后百頁,然后再根據字母順序查找。如果找完了z 字母開頭的漢字沒有找到張 ,則字典不存在張 |
非聚集索引 | 非聚集索引不重新組織表中的數據,具有獨立於數據行的結構,對每個鍵值都創建一個指向該鍵值的指針。 好比我們對所有漢字不進行排序,而是根據部首偏旁創建一個指向當前漢字的指針。當遇到一個我們不認識的漢字 張 ,我們不知道它的發音,所以我們選擇使用張 的偏旁部首``弓 來查找,如下圖所示可以找到張 610 所以根據這個610 定位到張 所在的位置。可以看到 張 上面弟 94 下面 弧 188 ,並沒有排過序。 |
唯一索引 | 不允許有相同數據列的索引 |
非唯一索引 | 普通索引 |
單一索引 | 針對一列的索引 |
復合索引 | 也叫組合索引,針對多列的索引 |
偏旁部首表
聚集索引
在每個數據頁的末尾,都有一個“行偏移量”的數組,這個數組記錄了每一個數據行的開頭在頁面中的起始位置,即每行數據開頭應該從頁頭偏移多少個字節。
聚合索引按照物理順序重排並不會重排數據行的順序,而是修改行偏移量的順序。
如先插入三條數據1,2,10 對應的偏移分別為100,200,300。
這時候插入一條數據8(偏移位置為150),大於2且小於10。數據庫並不會把8移動到2,10中間。而是修改行偏移量數組,將8的行偏移量移動2和10的中間。
復合索引查詢
- 使用復合索引在查詢的時候,最好將條件順序按照索引的順序排序,這樣效率最高。
CREATE INDEX index_columns ON person(name,age,zz) ;
如上述的復合索引這樣查詢效率最高:
SELECT * FROM person WHERE name=name AND age=age AND zz=zz
如下情況上述的復合索引起作用:
1.查詢name 2.查詢name,age 3.查詢name,age,zz
如下情況上述的復合索引不起作用:
1.查詢age 2.查詢zz 3.查詢age,zz
聚集和非聚集索引的使用場景
使用場景 | 聚集索引 | 非聚集索引 |
---|---|---|
列經常分組排序 | √ | √ |
返回某范圍內的數據 | √ | × |
很少的不同值 | × | × |
小數目不同值 | √ | × |
大數目不同值 | × | √ |
頻繁更新的列 | × | √ |
外鍵列 | √ | √ |
主鍵列 | √ | √ |
頻繁修改索引列 | × | √ |
主鍵和索引
在sqlserver中如果設置了主鍵,數據庫會自動創建聚集索引(除非聚集索引已存在)。主鍵的創建必須依賴於索引,可以主鍵的創建時候也可以聲明為非聚集的。
聚合索引主鍵
**1. ** 創建一個帶主鍵的表
CREATE TABLE person
(
id INT IDENTITY(1,1) NOT NULL,
name varchar(10),
age numeric(3,0),
zz varchar(100),
CONSTRAINT pk_person PRIMARY KEY(id)
);
**2. ** 嘗試添加一個聚集索引
CREATE CLUSTERED INDEX index_person_name ON person(name);
非聚合索引主鍵
**1. ** 創建一個帶非聚合索引主鍵的表
CREATE TABLE person
(
id INT IDENTITY(1,1) NOT NULL,
name varchar(10),
age numeric(3,0),
zz varchar(100),
CONSTRAINT pk_person PRIMARY KEY NONCLUSTERED(id)
);
**2. ** 嘗試添加一個聚集索引
CREATE CLUSTERED INDEX index_person_name ON person(name);
添加成功
**3. ** 嘗試刪除聚合索引
DROP INDEX index_person_name ON person
**4. ** 嘗試刪除非聚合索引
DROP INDEX index_person_name ON person
使用
通常,我們會在每個表中都建立一個自增id列,以區分每條數據。這樣可以讓數據庫中的數據按照id物理排序。但是由於id是自動生成的,我們並不知道每條數據的id號。
所以在實踐中無法根據id來檢索,由於每個表只能有一個聚集索引,所以聚集索引的就彌足珍貴。這樣使用聚集索引就操成了浪費。
我們也可以把需要提高查詢速度的字段建立一個復合索引都放到聚集索引中