最近看了一些關於mysql中索引的內容,如下的內容都是自已的理解,不正確的地方歡迎指正。mysql
索引的英文名字叫index(食指),就是指引的意思。若是把數據庫比爲一本書的話,索引就至關於書的目錄,它存在的意義就是使得咱們查找信息的時候更加的快。sql
上面提到過,索引之於數據庫如同目錄之於書本。就如同咱們在查閱一本書的時候,若是咱們在一本沒有目錄的書本上查找一個具體的信息,並且很是不幸的是咱們仍是第一次拿到這本書,對書中的內容和組織方式幾乎是一無所知,那咱們要查找這個具體的信息須要怎麼作呢?數據庫
固然,若是你的運氣足夠好的話,可能隨便一翻就直接到相關頁了,但你若是運氣不夠的話,恐怕最明智和幾乎惟一保險的作法就是從第一頁一直翻到最後一頁,若是很不幸的,你要查找的信息正好在書的最後一頁,恐怕你在沒有通讀全書以前是不會找到你要的東西的。性能優化
數據庫也是同樣,若是一張表對應於一本書,那若是不設置索引,那要找到一條記錄,就不得不從頭至尾的查找數據庫的第一條記錄,不過這種操做咱們有一個更專業的叫法稱爲全表掃描。數據結構
但若是把數據庫加上了索引,就等於一本書加上了目錄,說白了就是告訴咱們須要的數據在數據庫哪裏放着。以前咱們須要把書讀一遍才能查找到須要的信息,如今只須要讀目錄的對應章節就能夠了。想到這裏是否還有點小激動呢?性能
在mysql中,不一樣的引擎存儲索引的結構是不一樣的,咱們只舉最經常使用到的兩個存儲引擎:MYISAM和INNODB兩種存儲。優化
在MYISAM存儲引擎中,索引是單獨做爲一個文件存儲的,而在INNODB存儲引擎中,索引是和數據庫的數據存儲在一塊兒的。spa
目前的索引類型根據數據結構劃分大體能夠分爲全文索引、哈希索引和B+樹索引。設計
全文索引是在MYISAM存儲引擎下才能建立的索引,這裏不作討論。code
而對於最常用的索引,恐怕哈希索引和B+樹索引纔是使用的最多的。
B+樹索引在數據結構上講是一個B+樹(廢話)。它本質上講是一棵樹。但這個樹有必定的特色,主要有如下:
1.這個樹的度一般是很是大的(一般1000多都是正常的)
2.這個樹的高度通常是很低的。
3.這是一棵平衡樹,不會在增長索引內容的過程當中一條分支數據過多而另外一條分支幾乎沒有數據。
爲何要這樣設計呢?主要緣由就是爲了效率。查找數據的過程是尋道+讀取數據兩個過程的和。說白了,就是知道去哪裏找數據+把數據讀取出來的過程之和。從目前的數據的存儲來看,尋道(查找數據的存儲位置)的時間佔了大頭。而尋道的時間是由查找的次數來決定的,而在B+樹中全部的索引數據都是存儲在葉結點上的,所以從根結點到葉結點所走的次數(也就是樹的高度)就是尋道的次數,也就決定了數據的查找效率。因此咱們一切的努力都是爲了2特色服務的。
哈希索引就是一個字典結構。它會把要存入的全部數據都計算一個哈希值,而後作一個映射。當咱們要查找一個數據的時候,只要知道這條數據的哈希值的話,就能夠直接經過映射關係找到這條數據。
哈希索引很是適合哈希值不重複且一次只查找一條數據的狀況。但若是發生了哈希值重複的狀況,那重複的這些數據就會以鏈表的形式存儲在哈希值指向的區域內,要獲取指定的數據就只能遍歷這個鏈表了。
而若是查找的不是一條數據而是一個範圍內的數據,那由於哈希值是分散的形式存儲的,那索引就完成沒有做用了。
在mysql數據庫中,建立一條索引是很是容易的,咱們以一張以下的表爲例:
create table idx_student( id int unique not null, name varchar(30) not null, age tinyint , score int );
建立索引:
alter table idx_student add index idx_name (name);
這樣在idx_student表上就建立了一個以字段name爲查找字段的索引。咱們能夠看下錶idx_student的索引:
show index from idx_student;
在個人電腦上顯示的結果以下
這時候會很奇怪,明明只建立了一個name字段的索引,怎麼還會在id上也建立一個索引呢?由於在INNODB存儲引擎下,若是沒有顯式的建立索引,那麼它會自動找惟一的字段自發的建立一個索引(頗有些雷鋒精神)。
添加索引在性能上的優化在上面只是說了一說,如今咱們就切實的感覺下它的威力。
仍是以上面的表爲例,咱們先在表中添加一些數據:
delimiter ;; create procedure test_insert() begin declare i int default 1; while (i < 100000) do insert into idx_student (id ,name ,age,score ) values (i,concat('abc',i),10,10); set i = i+1; end while; commit ; end;; delimiter ; call test_insert();
這裏咱們插入了100000條數據,而後咱們進行一次查詢(未加索引):
select * from idx_student where name='abc6000';
加上了索引以後:
看來效果不明顯,若是咱們把上述的數字改爲1000000(一百萬),咱們來試下:
select * from idx_student where name='abc600000';
未加索引:
加上索引: