SQL---索引

今天我們一起學習並梳理一下數據庫中的索引的知識,帶着以下幾個問題,去深入的瞭解。

what:索引是什麼?索引有哪幾種類型?
why: 爲什麼要用到索引?作用是什麼?優點和缺點?
who: 誰去使用?開發人員或測試人員
where: 在代碼中或者sql查詢中
when: 開發階段、測試階段、性能優化階段
how: 怎麼用的,創建索引,刪除索引,索引失效

一、索引是什麼?

索引是一種用於快速查詢和檢索數據的數據結構。 索引的作用就相當於目錄的作用。打個比方: 我們在查字典的時候,如果沒有目錄,那我們就只能一頁一頁的去找我們需要查的那個字,速度很慢。如果有目錄了,我們只需要先去目錄裏查找字的位置,然後直接翻到那一頁就行了。

二、爲什麼要使用索引?

爲了提高查詢的效率。
索引一經建立,就由數據庫管理系統自動使用和維護,不需要用戶干預。建立索引是爲了加快數據的查詢效率

2.1索引的優點

①可以大大加快 數據的檢索速度(大大減少的檢索的數據量), 這也是創建索引的最主要的原因。畢竟大部分系統的讀請求總是大於寫請求的。
②另外,通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性

2.2索引的缺點

①創建索引和維護索引需要耗費許多時間:當對錶中的數據進行增刪改的時候,如果數據有索引,那麼索引也需要動態的修改,會降低 SQL 執行效率。
②佔用物理存儲空間 :索引需要使用物理文件存儲,也會耗費一定空間。

三、索引類型

3.1主鍵索引

①數據表的主鍵列使用的就是主鍵索引

②一張數據表有隻能有一個主鍵,並且主鍵不能爲 null,不能重複

③在 mysql 的 InnoDB 的表中,當沒有顯示的指定表的主鍵時,InnoDB 會自動先檢查表中是否有唯一索引的字段,如果有,則選擇該字段爲默認的主鍵,否則 InnoDB 將會自動創建一個 6Byte 的自增主鍵

3.2二級索引

二級索引又稱爲輔助索引,是因爲二級索引的葉子節點存儲的數據是主鍵。也就是說,通過二級索引,可以定位主鍵的位置。

唯一索引,普通索引,前綴索引等索引 均屬於二級索引

唯一索引(Unique Key) :唯一索引也是一種約束。唯一索引的屬性列不能出現重複的數據,但是允許數據爲 NULL,一張表允許創建多個唯一索引。 建立唯一索引的目的大部分時候都是爲了該屬性列的數據的唯一性,而不是爲了查詢效率。

普通索引(Index) :普通索引的唯一作用就是爲了快速查詢數據,一張表允許創建多個普通索引,並允許數據重複和 NULL。

前綴索引(Prefix) :前綴索引只適用於字符串類型的數據。前綴索引是對文本的前幾個字符創建索引,相比普通索引建立的數據更小,因爲只取前幾個字符。

3.3聚集索引

聚集索引:指索引項的排序方式和表中數據記錄排序方式一致的索引。它會根據聚集索引鍵的順序來存儲表中的數據,即對錶的數據按索引鍵的順序進行排序,然後重新存儲到磁盤上。因爲數據在物理存放只能有一種排列方式,所以一個表只能有一個聚集索引。比如字典中,用拼音查漢字,就是聚集索引。因爲正文中字都是按照拼音排序的。而用偏旁部首查漢字,就是非聚集索引,因爲正文中的字並不是按照偏旁部首排序的,我們通過檢字表得到正文中的字在索引中的映射,然後通過映射找到所需要的字。

聚集索引並不是一種單獨的索引類型,而是一種數據存儲方式。將數據存儲於索引放到了一塊,索引結構的葉子節點保存了行數據。另外,主鍵索引屬於聚集索引。

優點

聚集索引的查詢速度非常的快,因爲整個 B+樹本身就是一顆多叉平衡樹,葉子節點也都是有序的,定位到索引的節點,就相當於定位到了數據。

缺點

①依賴於有序的數據 :因爲 B+樹是多路平衡樹,如果索引的數據不是有序的,那麼就需要在插入時排序,如果數據是整型還好,否則類似於字符串或 UUID 這種又長又難比較的數據,插入或查找的速度肯定比較慢。
②更新代價大 : 如果對索引列的數據被修改時,那麼對應的索引也將會被修改,而且況聚集索引的葉子節點還存放着數據,修改代價肯定是較大的,所以對於主鍵索引來說,主鍵一般都是不可被修改的。

3.4非聚集索引

非聚集索引:與聚集索引相反,索引順序與物理存儲順序不一致。通俗點說:非聚集索引即索引結構和數據分開存放的索引。二級索引屬於非聚集索引

優點

更新代價比聚集索引要小 。非聚集索引的更新代價就沒有聚集索引那麼大了,非聚集索引的葉子節點是不存放數據的。

缺點

非聚集索引也依賴於有序的數據。可能會二次查詢(回表) :這應該是非聚集索引最大的缺點了。 當查到索引對應的指針或主鍵後,可能還需要根據指針或主鍵再到數據文件或表中查詢。

四、索引用法

4.1創建索引

CREATE UNION/CLUSTERED/NONCLUSTERED INDEX 索引名 ON 表名 (列名)

4.2刪除索引

DROP INDEX 表名.索引名

4.3怎樣查看一條SQL使用了索引?

 沒有創建索引,查詢時如下:

 給loc字段添加索引,創建索引之後:

4.4索引失效的幾種情況

失效的第1種情況
select * from emp where ename like '%T';

ename上即使添加了索引,也不會走索引,爲什麼?
原因是因爲模糊匹配當中以“%”開頭了,mysql找不到。
解決方案:儘量避免模糊查詢的時候以“%”開始。這是一種優化的手段/策略。

失效的第2種情況:
使用or的時候會失效,如果使用or那麼要求or兩邊的條件字段都要有索引,纔會走索引,如果or其中一邊有一個字段沒有索引,那麼另一個字段上的索引也會失效。
解決方案:
不建議使用or,所以這就是爲什麼不建議使用or的原因。
或使用union聯合查詢。
舉例:
dept表,loc字段有索引,deptname字段沒有索引
select * from dept where loc = '福建' or deptname = '信息部';
--- 查詢位於福建的或者信息部的部門信息
以上sql語句,由於deptname沒有索引,會導致loc的索引失效,可以使用union聯合查詢:
select * from dept where loc = '福建' union select * from dept where deptname = '信息部';這樣loc字段的索引還是生效的。

失效的第3種情況:
使用複合索引的時候,沒有用到左側的字段作爲查找條件,索引失效
什麼是複合索引?
兩個字段,或者更多的字段聯合起來添加一個索引,叫做複合索引。
create index emp_job_sal_index on emp(job,sal);

索引正常:explain select * from emp where job = 'MANAGER';
索引失效:explain select * from emp where sal = 800;

失效的第4種情況:
在where當中索引列參加了運算,索引失效。
create index emp_sal_index on emp(sal);

索引正常:explain select * from emp where sal = 800;
索引失效:explain select * from emp where sal+1 = 800;

失效的第5種情況:
在where當中索引列使用了函數

ename字段有索引
explain select * from emp where lower(ename) = 'smith';

 五、其他問題答疑

問題1:在一個表中可以創建幾個聚集索引?可以創建多個非聚集索引嗎?
回答:在一個表中,只能創建1個聚集索引,可以創建多個非聚集索引


問題2:聚集索引一定是唯一性索引,是否正確?反之呢?
回答:聚集索引一定是唯一性索引,唯一性索引不一定是聚集索引,它(唯一性索引)可以是聚集也可以是非聚集索引不指定索引類型的情況下,則默認爲非聚集索引


問題3:不管對錶進行什麼類型操作,在表上建立的索引越多越能提高數據操作效率,是否正確?
回答:不是


問題4:使用視圖可以加快數據的查詢速度嗎?這句話對嗎?爲什麼?
回答:不對,因爲視圖並沒有保存數據,對視圖的查詢要轉換成對基本表的查詢,這個轉換需要時間,它會降低查詢效率

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章