文章目錄
一、索引是什麼?優點、缺點
1、索引的官方定義
MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構。 可以得到索引的本質:索引是數據結構
。
你可以簡單理解爲“排好序的快速查找數據結構”。
2、索引的優點與缺點
# 優點
1. 類似大學圖書館建書目索引,提高數據檢索的效率,降低數據庫的IO成本
2. 通過索引列對數據進行排序,降低數據排序的成本,降低了CPU的消耗
# 缺點
實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄,所以索引列也是要佔用空間的
雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行INSERT、UPDATE和DELETE。
# 因爲更新表時,MySQL不僅要保存數據,還要保存一下索引文件每次更新添加了索引列的字段, 都會調整因爲更新所帶來的鍵值變化後的索引信息
索引只是提高效率的一個因素,如果你的MySQL有大數據量的表,就需要花時間研究建立最優秀的索引,或優化查詢語句
二、mysql索引結構
閱讀之前建議看看磁盤塊索引詳解:https://blog.csdn.net/weixin_44571270/article/details/105899656
1、BTree索引
原理圖
每個節點都存儲key和data,所有節點組成這棵樹,並且葉子節點指針爲null,只有樹枝節點、根結點纔有指針。
2、B+Tree索引
只有葉子節點存儲data,葉子節點包含了這棵樹的所有鍵值,葉子節點不存儲指針。B+樹上增加了順序訪問指針,也就是每個葉子節點增加一個指向相鄰葉子節點的指針,這樣一棵樹成了數據庫系統實現索引的首選數據結構。
最主要的原因是這棵樹矮胖,呵呵。一般來說,索引很大,往往以索引文件的形式存儲的磁盤上,索引查找時產生磁盤I/O消耗,相對於內存存取,I/O存取的消耗要高几個數量級,所以評價一個數據結構作爲索引的優劣最重要的指標就是在查找過程中磁盤I/O操作次數的時間複雜度。樹高度越小,I/O次數越少。
# 爲什麼B+樹成爲數據庫系統實現索引的首選數據結構
1. 那爲什麼是B+樹而不是B樹呢,因爲它根節點與樹枝節點不存儲data
2. 這樣一個節點就可以存儲更多的key。這樣整個樹相比B樹會更加矮胖,I/O次數更少!
3. MyISAM存儲引擎採用b-樹實現索引,innodb採用b+樹實現索引,因此這也是innodb用的更加多的原因之一
3、B+樹與B-樹的區別
# B+樹與B-樹的區別
1. 從存儲數據來看
b-樹,葉子節點跟非葉子節點都儲存數據
b+樹,只有在葉子節點儲存數據
2. 從結構上來看
B樹:有序數組+平衡多叉樹;
B+樹:有序數組鏈表+平衡多叉樹;
# B+樹的特點:
1、B+樹的層級更少:相較於B樹B+每個非葉子節點存儲的關鍵字數更多,樹的層級更少所以查詢數據更快;
2、B+樹查詢速度更穩定:B+所有關鍵字數據地址都存在葉子節點上,所以每次查找的次數都相同所以查詢速度要比B樹更穩定;
3、B+樹天然具備排序功能:B+樹所有的葉子節點數據構成了一個有序鏈表,在查詢大小區間的數據時候更方便,數據緊密性很高,緩存的命中率也會比B樹高。
4、B+樹全節點遍歷更快:B+樹遍歷整棵樹只需要遍歷所有的葉子節點即可,,而不需要像B樹一樣需要對每一層進行遍歷,這有利於數據庫做全表掃描。
# B樹相對於B+樹的優點
如果經常訪問的數據離根節點很近,而B樹的非葉子節點本身存有關鍵字其數據的地址,所以這種數據檢索的時候會要比B+樹快。
4、聚簇索引與非聚簇索引
也叫聚集索引與非聚集索引
- MyISAM
data存的是數據地址。索引是索引,數據是數據。索引放在XX.MYI文件中,數據放在XX.MYD文件中,所以也叫非聚集索引。
- InnoDB
data存的是數據本身。索引也是數據。數據和索引存在一個XX.IDB文件中,所以也叫聚集索引。
MyISAM 與InnoDB建表文件對比:https://blog.csdn.net/weixin_44571270/article/details/106710860
1. 聚簇索引的好處:
• 按照聚簇索引排列順序,查詢顯示一定範圍數據的時候,由於數據都是緊密相連,數據庫不用從多個數據塊中提取數據,所以節省了大量的io操作。
2. 聚簇索引的限制:
• 對於mysql數據庫目前只有innodb數據引擎支持聚簇索引,而Myisam並不支持聚簇索引。
• 由於數據物理存儲排序方式只能有一種 ,所以每個Mysql的表只能有一個聚簇索引。一般情況下就是該表的主鍵 。
• 爲了充分利用聚簇索引的聚簇的特性,所以innodb表的主鍵列儘量選用有序的順序id,而不建議用無序的id,比如uuid這種。(參考聚簇索引的好處。)
這裏說明了主鍵索引爲何採用自增的方式:1、業務需求,有序。2、能使用到聚簇索引
5、full-text全文索引
全文索引(也稱全文檢索)是目前搜索引擎使用的一種關鍵技術。它能夠利用【分詞技術】等多種算法智能分析出文本文字中關鍵詞的頻率和重要性,然後按照一定的算法規則智能地篩選出我們想要的搜索結果。
CREATE TABLE `article` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(200) DEFAULT NULL,
`content` text,
PRIMARY KEY (`id`),
FULLTEXT KEY `title` (`title`,`content`) # 全文索引
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
限制:
mysql5.6.4以前只有Myisam支持,5.6.4版本以後innodb才支持,但是官方版本不支持中文分詞,需要第三方分詞插件。
5.7以後官方支持中文分詞。
隨着大數據時代的到來,關係型數據庫應對全文索引的需求已力不從心,逐漸被 solr,elasticSearch等專門的搜索引擎所替代。
6、Hash索引
Hash索引只有Memory, NDB兩種引擎支持,Memory引擎默認支持Hash索引,如果多個hash值相同,出現哈希碰撞,那麼索引以鏈表方式存儲。
NoSql採用此種索引結構。
7、R-Tree索引
R-Tree在mysql很少使用,僅支持geometry數據類型,支持該類型的存儲引擎只有myisam、bdb、innodb、ndb、archive幾種。
相對於b-tree,r-tree的優勢在於範圍查找。
三、mysql索引分類
1、主鍵索引
設定爲主鍵後數據庫會自動建立索引,innodb爲聚簇索引
// 隨表一起建索引:
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),
PRIMARY KEY(id)
);
unsigned (無符號的)
使用 AUTO_INCREMENT 關鍵字的列必須有索引(只要有索引就行)。
CREATE TABLE customer2 (id INT(10) UNSIGNED ,customer_no VARCHAR(200),customer_name VARCHAR(200),
PRIMARY KEY(id)
);
// 單獨建主鍵索引:
ALTER TABLE customer
add PRIMARY KEY customer(customer_no);
// 刪除主鍵索引:
ALTER TABLE customer
drop PRIMARY KEY ;
// 修改主鍵索引:
必須先刪除掉(drop)原索引,再新建(add)索引
2、單值索引
即一個索引只包含單個列,一個表可以有多個單列索引
索引建立成哪種索引類型?
根據數據引擎類型自動選擇的索引類型
除開 innodb 引擎主鍵默認爲聚簇索引 外。 innodb 的索引都採用的 B+TREE
myisam 則都採用的 B-TREE索引
// 隨表一起建索引:
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),
PRIMARY KEY(id),
KEY (customer_name)
);
注意:隨表一起建立的索引 索引名同 列名(customer_name)
// 單獨建單值索引:
CREATE INDEX idx_customer_name ON customer(customer_name);
// 刪除索引:
DROP INDEX idx_customer_name ;
3、唯一索引
索引列的值必須唯一,但允許有空值
// 隨表一起建索引:
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),
PRIMARY KEY(id),
KEY (customer_name),
UNIQUE (customer_no)
);
注意:建立唯一索引時必須保證所有的值是唯一的(除了null),若有重複數據,會報錯。
// 單獨建唯一索引:
CREATE UNIQUE INDEX id x_customer_no ON customer(customer_no);
// 刪除索引:
DROP INDEX idx_customer_no on customer ;
4、複合索引
即一個索引包含多個列
在數據庫操作期間,複合索引比單值索引所需要的開銷更小(對於相同的多個列建索引)
當表的行數遠大於索引列的數目時可以使用複合索引
// 隨表一起建索引:
CREATE TABLE customer (id INT(10) UNSIGNED AUTO_INCREMENT ,customer_no VARCHAR(200),customer_name VARCHAR(200),
PRIMARY KEY(id),
KEY (customer_name),
UNIQUE (customer_name),
KEY (customer_no,customer_name)
);
// 單獨建索引:
CREATE INDEX idx_no_name ON customer(customer_no,customer_name);
// 刪除 索引:
DROP INDEX idx_no_name on customer ;
5、基本語法
// 創建
ALTER mytable ADD [UNIQUE ] INDEX [indexName] ON (columnname(length))
// 刪除
DROP INDEX [indexName] ON mytable;
// 查看
SHOW INDEX FROM table_name\G
// 使用ALTER命令有四種方式來添加數據表的索引:
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 該語句添加一個主鍵,這意味着索引值必須是唯一的,且不能爲NULL。
ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 這條語句創建索引的值必須是唯一的(除了NULL外,NULL可能會出現多次)。
ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出現多次。
ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):該語句指定了索引爲 FULLTEXT ,用於全文索引。
6、輔助索引
輔助索引:查詢數據的時候不可能都是用id作爲篩選條件,也可能會用name,password等字段信息,那麼這個時候就無法利用到聚集索引(主鍵索引)
的加速查詢效果。就需要給其他字段建立索引,這些索引就叫輔助索引(單值索引、唯一索引、複合索引)
特點:輔助索引的葉子結點存放的是輔助索引建立的字段所在的那張表的主鍵的聚集索引數據塊的地址
。
查找流程:當通過輔助索引查找時,先通過輔助索引,獲取聚集索引,再通過聚集索引查找到相應的數據。
輔助索引又分爲覆蓋索引和非覆蓋索引:
- 覆蓋索引
下面語句叫覆蓋索引:只在輔助索引的葉子節點中就已經找到了所有我們想要的數據
select name from user where name='jason';
- 非覆蓋索引
下面語句叫非覆蓋索引,雖然查詢的時候命中了索引字段name,但是要查的是age字段,所以還需要利用聚集索引去查找!
select age from user where name='jason';
四、創建索引的原則
1、哪些情況需要創建索引
1. 主鍵自動建立唯一索引
2. 頻繁作爲查詢條件的字段應該創建索引(where 後面的語句)
3. 查詢中與其它表關聯的字段,外鍵關係建立索引
A表關聯B表:A join B,on 後面的連接條件 既 A 表查詢 B 表的條件。所以 B 表被關聯的字段建立索引能大大提高查詢效率
因爲在 join 中,join 左邊的表會用每一個字段去遍歷 B 表的所有的關聯數據,相當於一個查詢操作
4. 單鍵/組合索引的選擇問題,who?(在高併發下傾向創建組合索引)
5. 查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度
group by 和 order by 後面的字段有索引大大提高效率
6. 查詢中統計或者分組字段
2、哪些情況不要創建索引
1. 表記錄太少
2. 經常增刪改的表
Why:提高了查詢速度,同時卻會降低更新表的速度
如對錶進行INSERT、UPDATE和DELETE。 因爲更新表時,MySQL不僅要保存數據,還要保存一下索引文件
3. Where條件裏用不到的字段不創建索引
4. 數據重複且分佈平均的表字段,因此應該只爲最經常查詢和最經常排序的數據列建立索引。 注意,如果某個數據列包含許多重複的內容,爲它建立索引就沒有太大的實際效果。