1.什么是索引
在關系數據庫中,索引是一種單獨的、物理的數對數據庫表中一列或多列的值進行排序的一種存儲結構。
它是某個表中一列或若干列值的集合和相應的指向表中物理標識這些值的數據頁的邏輯指針清單
2.索引的優點
(1)通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性。
(2)可以加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。
(3)在使用分組和排序子句進行數據查詢時,可以減少查詢中分組和排序的時間。
(4)通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。
3.索引的缺點
(1)創建索引和維護索引要耗費時,這種時間隨著數據量的增加而增加。
(2)索引需要占物理空間,除了數據表占數據空間之外,每一個索引還要占一定的物理空間,如果要建立聚簇索引,那么需要的空間就會更大。
(3)當對表中的數據進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了數據的維護速度。
4.索引的分類
(1)B樹索引 (主要,默認索引):mysql innodb默認的索引類型就是 Btree索引(B樹,B-樹,B+樹,B*樹),Binary Tree,就是一個二叉樹。
(2)hash索引:Hash索引結構的特殊性,其檢索效率非常高,索引的檢索可以一次定位,不像B-Tree索引需要從根節點到枝節點,
最后才能訪問到頁節點這樣多次的IO訪問,所以Hash索引的查詢效率要遠高于B-Tree索引,僅僅能滿足"=" "IN" 和 "<=>" 查詢,不能使用范圍查詢。
只有 Memory存儲引擎顯示支持hash索引。
(3)FULLTEXT索引 (全文檢索,MYISAM和INNODB引擎都支持了)。
(4)R-tree索引 (用于對GIS數據類型創建 SPATIAL 空間索引)
5.索引按邏輯的分類
(1)主鍵索引
(2)普通索引 or 單列索引
(3)多列索引(復合索引)
(4)唯一索引或者非唯一索引
(5)空間索引
6.B-樹的由來
為迎合磁盤與內存的速度差,減少磁盤IO次數,提高性能
注(數據量非常大時,內存不夠用,大部分數據只能存放在磁盤上,只有需要的數據才加載到內存中。
一般而言內存訪問的時間約為 50 ns(納秒),而磁盤在 10 ms (毫秒))
7.B-樹和B+樹的區別
(1)B+樹內節點不存儲數據,所有 data 存儲在葉節點導致查詢時間復雜度固定為 log(n)。而B-樹查詢時間復雜度不固定,與 key 在樹中的位置有關, 最好為O(1)。
(2)B+樹葉節點兩兩相連可大大增加區間訪問性,可使用在范圍查詢等,而B-樹每個節點 key 和 data 在一起,則無法區間查找。
(3)B+樹更適合外部存儲。由于內節點無 data 域,每個節點能索引的范圍更大更精確
(4)在數據結構上:B樹為有序數組+平衡多叉樹,而B+樹為有序數組鏈表+平衡多叉樹
8.為什么 Mysql 使用B+樹?
Mysql 是一種關系型數據庫,區間訪問是常見的一種情況,而 B-樹并不支持區間訪問(可參見上圖),
而B+樹由于數據全部存儲在 葉子節點,并且通過指針串在一起,這樣就很容易的進行區間遍歷甚至全部遍歷。
(1)B+樹葉節點兩兩相連可大大增加區間訪問性,可使用在范圍查詢等,而B-樹每個節點 key 和 data 在一起,則無法區間查找?
(2)B+樹的查詢效率更加穩定,數據全部存儲在葉子節點,查詢時間復雜度固定為 O(log n)
(3)B+樹更適合外部存儲。由于內節點無 data 域,每個節點能索引的范圍更大更精確
9.mysql索引使用
(1)創建索引
create index index_name on table_name(col_name);
(2)為已創建的表增加索引
alter table table_name add index index_name(col_name);
(3)查看已創建索引:
show index from yzjtestdb.yzjtest_m1
(4)索引使用:
explain select * from yzjtestdb.yzjtest_m1 where name = 'yzjtest30000010';
explain select * from yzjtestdb.yzjtest_m1 where tel = '13379855952';
(5)索引刪除:
drop index yzjtest_m1_inx_name on yzjtest_m1;
drop index yzjtest_m1_inx_tel on yzjtest_m1;
(6)復合索引使用管理
# 語法:
create index index_name on table_name(col_name1,col_name2);
alter table table_name add index index_name(col_name1,col_name2);
# 案例:
use yzjtestdb;
create index yzjtest_m1_inx_name_tel on yzjtestdb.yzjtest_m1(NAME,TEL);
alter table yzjtestdb.yzjtest_m1 add index yzjtest_m1_inx_name_tel(NAME,TEL);
查看已創建索引:
show index from yzjtestdb.yzjtest_m1;
# 索引使用:
explain select * from yzjtestdb.yzjtest_m1 where name = 'yzjtest30000010'and tel = '13379855952';
# 索引刪除:
drop index yzjtest_m1_inx_name_tel on yzjtest_m1;
?