點贊多大膽,就有多大產!開源促使進步,獻給每一位技術使用者和愛好者!
乾貨滿滿,擺好姿勢,點贊發車
前言
不管在學習數據庫或者在面試時都會遇到索引這個玩意兒,是我們走向光頭必不可少的一項技能!對於數據庫如何優化,都會想到加索引,我們就來說說到底什麼是索引,怎麼用,如何用好等!索引數據結構請戳《搞懂MySQL數據庫索引數據結構這一篇足夠從此不再萌萌噠》,話不多說直接開搞!
索引你做個自我介紹
各位看客老爺我是索引,我其實很簡單不像外邊的妖豔賤貨那麼複雜,官網上說人家是存儲引擎用於快速找到記錄的一種數據結構,不通的存儲引擎對索引的實現方式不同,一般存儲在磁盤中,爲了減少數據掃描的次數,將隨機I/O轉變爲順序I/O,幫助我們在分組、排序等操作時,避免使用臨時表。比如新華字典,要去找一個字可以通過翻目錄用偏旁,拼音等來找一個字,如果沒有這個目錄你就得一頁一頁去找,索引就是數據庫性能調優的基礎方式,常用於實現數據的快速檢索,接下來我要給大家好好介紹一下索引。
MySql數據訪問方式
在Mysql中通常有以下兩種方式來檢索一行數據,如以下數據表
id | name | age |
1 | 石添添 | 18 |
2 | 石小添 | 19 |
3 | 石笑天 | 10 |
4 | 石小索 | 15 |
5 | 石小引 | 21 |
6 | 石以初 | 20 |
順序訪問
順序訪問是執行全表掃描,比如我們要檢索age爲15的用戶,從頭到尾逐行遍歷,直到在無序的行數據中找到符合條件的目標數據。這種方式實現比較簡單,但是當表中有大量數據的時候,效率非常低下。例如,在幾千萬條數據中查找少量的數據時,使用順序訪問方式將會遍歷所有的數據,花費大量的時間,顯然會影響數據庫的處理性能!
索引訪問
索引訪問是通過遍歷索引來直接訪問表中記錄行的方式。使用這種方式的前提是對錶建立一個索引,在列上創建了索引之後,查找數據時可以直接根據該列上的索引找到對應記錄行的位置,從而快捷地查找到數據。
例如:我們在age列上添加索引,數據庫系統就建立了一張索引列到實際記錄的映射表,當需要查找age爲15的數據時,會先在age索引上找到該記錄,然後通過映射表直接找到數據行,並且返回該行數據。因爲掃描索引的速度一般遠遠大於掃描實際數據行的速度,所以採用索引的方式可以大大提高數據庫的工作效率。
至此我們知道索引是一種數據結構,需要單獨存放可以增快我們的查詢效率,是數據庫優化的一種基礎而重要方案,數據庫搜索數據順序訪問和索引訪問兩種方式。
索引創建
MySql提供三種創建索引的方法,注意InnoDB引擎會自動在主鍵上添加索引
使用CREATE INDEX 語句
用於在表已存在添加索引
語法
CREATE INDEX <索引名> ON <表名> (<列名> [<長度>] [ ASC | DESC])
說明
- 索引名:指定索引名。一個表可以創建多個索引,但每個索引名在表中唯一
- 表名:指定在哪個表中創建索引
- 列名:指定要創建索引的列名。通常可以考慮將查詢語句中在 JOIN 子句和 WHERE 子句裏經常出現的列作爲索引列,可以是一列也可以是多列,一列的稱之爲單列索引,多列成爲組合索引
- 長度:可選項。指定使用列前的 length 個字符來創建索引。使用列的一部分創建索引有利於減小索引文件的大小,節省索引列所佔的空間。在某些情況下,只能對列的前綴進行索引。索引列的長度有一個最大上限 255 個字節(MyISAM 和 InnoDB 表的最大上限爲 1000 個字節),如果索引列的長度超過了這個上限,就只能用列的前綴進行索引。另外,BLOB 或 TEXT 類型的列也必須使用前綴索引
- ASC | DESC:可選項。ASC指定索引按照升序來排列,DNSC指定索引按照降序來排列,默認爲ASC
例子
CREATE INDEX index_user_age ON tb_user(age);
使用CREATE TABLE 語句
用於在創建表(CREATE TABLE)時創建,在CREATE TABLE 語句下添加
語法
1、表示在創建新表的同時創建該表的索引
KEY | INDEX [<索引名>] [<索引類型>] (<列名>,…)
2、表示在創建新表的同時創建該表的唯一性索引
UNIQUE [ INDEX | KEY] [<索引名>] [<索引類型>] (<列名>,…)
例子
CREATE TABLE student(
id INT PRIMARY KEY,
`name` VARCHAR(10) NOT NULL,
class VARCHAR(10) NOT NULL,
INDEX(name) -- 在name列上創建索引
);
使用 ALTER TABLE 語句
在使用 ALTER TABLE 語句修改表的同時,可以向已有的表添加索引。具體的做法是在 ALTER TABLE 語句中添加以下語法成分的某一項或幾項
語法
1、在修改表的同時爲該表添加索引
ADD INDEX [<索引名>] [<索引類型>] (<列名>,…)
2、在修改表的同時爲該表添加唯一性索引
ADD UNIQUE [ INDEX | KEY] [<索引名>] [<索引類型>] (<列名>,…)
例子
ALTER TABLE student ADD INDEX index_class (class);
查看索引
語句
SHOW INDEX FROM <表名> [ FROM <數據庫名>]
例子
SHOW index FROM table_name;
說明
- 表名:查詢索引的表名
- 數據庫名:要查詢的表在哪個數據庫,這個可以使用數據庫名.表名替代
- Table:表名
- No_unique:用於顯示該索引是否是唯一索引。若不是唯一索引,則該列的值顯示爲 1;若是唯一索引,則該列的值顯示爲 0
- Key_name:索引的名稱,不指定名稱就是列名
- Seq_in_index:索引中的列序列號,從1開始計數
- Column_name:列名
- Collation:顯示列以何種順序存儲在索引中。在 MySQL 中,升序顯示值“A”,若顯示爲 NULL,則表示無分類
- Cardinality:顯示索引中唯一值數目的估計值。基數根據被存儲爲整數的統計數據計數,所以即使對於小型表,該值也沒有必要是精確的。基數越大,當進行聯合時,MySQL 使用該索引的機會就越大
- Sub_part:若列只是被部分編入索引,則爲被編入索引的字符的數目。若整列被編入索引,則爲 NULL
- Packed:指示關鍵字如何被壓縮。若沒有被壓縮,則爲 NULL
- Null:用於顯示索引列中是否包含 NULL。若列含有 NULL,則顯示爲 YES
- Index_type:顯示索引使用的類型和方法(BTREE、FULLTEXT、HASH、RTREE)
- Comment:顯示評註
- Index_comment:顯示評註
刪除索引
當老闆不再用我的時候,可以使用 DROP INDEX 語句或 ALTER TABLE 語句來刪除我!
刪除
語法
DROP INDEX <索引名> ON <表名>
或者再ALTER TABLE語句後邊添加
DROP INDEX index_name:表示刪除名稱爲 index_name 的索引。
注意:如果刪除的列是索引的組成部分,那麼在刪除該列時,也會將該列從索引中刪除;如果組成索引的所有列都被刪除,那麼整個索引將被刪除
例子
DROP INDEX name ON student;
或
ALTER TABLE student DROP INDEX index_class;
索引分類
根據索引的用途在邏輯上可以分爲以下五種
普通索引
普通索引是最基本的索引類型,唯一任務是加快對數據的訪問速度,沒有任何限制。創建普通索引時,通常使用的關鍵字是 INDEX 或 KEY
唯一性索引
唯一性索引是不允許索引列具有相同索引值的索引。如果能確定某個數據列只包含彼此各不相同的值,在爲這個數據列創建索引的時候就應該用關鍵字 UNIQUE 把它定義爲一個唯一性索引。創建唯一性索引的目的往往不是爲了提高訪問速度,而是爲了避免數據出現重複
主鍵索引
主鍵索引是一種唯一性索引,即不允許值重複或者值爲空,並且每個表只能有一個主鍵。主鍵可以在創建表的時候指定,也可以通過修改表的方式添加,必須指定關鍵字 PRIMARY KEY,注意一張表只能有一個主鍵
空間索引
空間索引主要用於地理空間數據類型 GEOMETRY
全文索引
全文索引只能在 VARCHAR 或 TEXT 類型的列上創建,並且只能在 MyISAM 存儲引擎
在實際使用中,索引通常被創建成單列索引和組合索引
- 單列索引就是索引只包含原表的一個列
- 組合索引也稱爲複合索引或多列索引,相對於單列索引來說,組合索引是將原表的多個列共同組成一個索引
敲黑板:一個表可以有多個單列索引,但這些索引不是組合索引。一個組合索引實質上爲表的查詢提供了多個索引,以此來加快查詢速度。比如,在一個表中創建了一個組合索引(c1,c2,c3),在實際查詢中,系統用來實際加速的索引有三個:單個索引(c1)、雙列索引(c1,c2)和多列索引(c1,c2,c3)
索引注意事項和使用原則
注意事項
創建索引雖然可以提升Mysql的查詢性能,但是索引在使用的時候也不是爲所欲爲,越多越好,需要注意以下幾點
- 索引的創建和維護需要消耗時間,這個時間會隨着數據量的增多而增加
- 除了表中數據佔用控件,索引也需要佔用一定空間,如果要建立聚簇索引,那麼需要的空間就會更大
- 當對錶中的數據進行增加、刪除和修改的時候,索引也要動態地維護,這樣就降低了數據的維護速度
使用原則
- 在經常需要搜索的列上建立索引,可以加快搜索的速度
- 在作爲主鍵的列上創建索引,強制該列的唯一性,並組織表中數據的排列結構,在InnoDB存儲引擎,默認給主鍵添加索引
- 在經常使用表連接的列上創建索引,這些列主要是一些外鍵,可以加快表連接的速度
- 在經常需要根據範圍進行搜索的列上創建索引,因爲索引已經排序,所以其指定的範圍是連續的
- 在經常需要排序的列上創建索引,因爲索引已經排序,所以查詢時可以利用索引的排序,加快排序查詢
- 在經常出現在WHERE子句中的列上添加索引,加快條件的判斷速度
以下場景建議不要添加索引,添加了反而增加數據庫的壓力,產生負面影響
- 對於那些在查詢中很少使用或參考的列不應該創建索引。因爲這些列很少使用到,所以有索引或者無索引並不能提高查詢速度。相反,由於增加了索引,反而系統要去維護和存儲,增大壓力
- 對於那些只有很少數據值的列也不應該創建索引。因爲這些列的取值很少,例如用戶表的愛好列。查詢結果集的數據行佔了表中數據行的很大比例,增加索引並不能明顯加快檢索速度
- 對於那些定義爲 TEXT、IMAGE 和 BIT 數據類型的列不應該創建索引。因爲這些列的數據量要麼相當大,要麼取值很少
- 當修改性能遠遠大於檢索性能時,不應該創建索引。因爲修改性能和檢索性能是互相矛盾的。當創建索引時,會提高檢索性能,降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。因此,當修改性能遠遠大於檢索性能時,不應該創建索引,就是表中某個字段經常修改不要添加索引,因爲會動態維護!
路漫漫其修遠兮,吾將上下而求索
本文若有任何看不懂,或者有錯誤的地方歡迎大家評論區留言,我時時關注哦