浅谈数据库索引
1.什么是索引
?
數(shù)據(jù)庫索引好比是一本書前面的目錄,能加快數(shù)據(jù)庫的查詢速度。
例如這樣一個查詢:select * from table1 where id=44。如果沒有索引,必須遍歷整個表,直到ID等于44的這一行被找到為止;有了索引之后(必須是在ID這一列上建立的索引),直接在索引里面找 44(也就是在ID這一列找),就可以得知這一行的位置,也就是找到了這一行??梢?#xff0c;索引是用來定位的。
索引分為聚簇索引和非聚簇索引兩種,聚簇索引 是按照數(shù)據(jù)存放的物理位置為順序的,而非聚簇索引就不一樣了;聚簇索引能提高多行檢索的速度,而非聚簇索引對于單行的檢索很快。
建立索引的目的是加快對表中記錄的查找或排序。
為表設(shè)置索引要付出代價的:一是增加了數(shù)據(jù)庫的存儲空間,二是在插入和修改數(shù)據(jù)時要花費較多的時間(因為索引也要隨之變動)。
2.為什么要創(chuàng)建索引
?
創(chuàng)建索引可以大大提高系統(tǒng)的性能。
第一,通過創(chuàng)建唯一性索引,可以保證數(shù)據(jù)庫表中每一行數(shù)據(jù)的唯一性。
第二,可以大大加快數(shù)據(jù)的檢索速度,這也是創(chuàng)建索引的最主要的原因。
第三,可以加速表和表之間的連接,特別是在實現(xiàn)數(shù)據(jù)的參考完整性方面特別有意義。
第四,在使用分組和排序子句進行數(shù)據(jù)檢索時,同樣可以顯著減少查詢中分組和排序的時間。
第五,通過使用索引,可以在查詢的過程中,使用優(yōu)化隱藏器,提高系統(tǒng)的性能。
也許會有人要問:增加索引有如此多的優(yōu)點,為什么不對表中的每一個列創(chuàng)建一個索引呢?因為,增加索引也有許多不利的方面。
第一,創(chuàng)建索引和維護索引要耗費時間,這種時間隨著數(shù)據(jù)量的增加而增加。
第二,索引需要占物理空間,除了數(shù)據(jù)表占數(shù)據(jù)空間之外,每一個索引還要占一定的物理空間,如果要建立聚簇索引,那么需要的空間就會更大。
第三,當(dāng)對表中的數(shù)據(jù)進行增加、刪除和修改的時候,索引也要動態(tài)的維護,這樣就降低了數(shù)據(jù)的維護速度。
3.在哪建索引
?
索引是建立在數(shù)據(jù)庫表中的某些列的上面。在創(chuàng)建索引的時候,應(yīng)該考慮在哪些列上可以創(chuàng)建索引,在哪些列上不能創(chuàng)建索引。一般來說,應(yīng)該在這些列上創(chuàng)建索引:
1.在經(jīng)常需要搜索的列上,可以加快搜索的速度;
2.在作為主鍵的列上,強制該列的唯一性和組織表中數(shù)據(jù)的排列結(jié)構(gòu);
3.在經(jīng)常用在連接的列上,這些列主要是一些外鍵,可以加快連接的速度;在經(jīng)常需要根據(jù)范圍進行搜索的列上創(chuàng)建索引,因為索引已經(jīng)排序,其指定的范圍是連續(xù)的;
4.在經(jīng)常需要排序的列上創(chuàng)建索引,因為索引已經(jīng)排序,這樣查詢可以利用索引的排序,加快排序查詢時間;
5.在經(jīng)常使用在WHERE子句中的列上面創(chuàng)建索引,加快條件的判斷速度。
同樣,對于有些列不應(yīng)該創(chuàng)建索引。一般來說,不應(yīng)該創(chuàng)建索引的的這些列具有下列特點:
第一,對于那些在查詢中很少使用或者參考的列不應(yīng)該創(chuàng)建索引。這是因為,既然這些列很少使用到,因此有索引或者無索引,并不能提高查詢速度。相反,由于增加了索引,反而降低了系統(tǒng)的維護速度和增大了空間需求。
第二,對于那些只有很少數(shù)據(jù)值的列也不應(yīng)該增加索引。這是因為,由于這些列的取值很少,例如人事表的性別列,在查詢的結(jié)果中,結(jié)果集的數(shù)據(jù)行占了表中數(shù)據(jù)行的很大比例,即需要在表中搜索的數(shù)據(jù)行的比例很大。增加索引,并不能明顯加快檢索速度。
第三,對于那些定義為text, image和bit數(shù)據(jù)類型的列不應(yīng)該增加索引。這是因為,這些列的數(shù)據(jù)量要么相當(dāng)大,要么取值很少,不利于使用索引。
第四,當(dāng)修改性能遠遠大于檢索性能時,不應(yīng)該創(chuàng)建索引。這是因為,修改性能和檢索性能是互相矛盾的。當(dāng)增加索引時,會提高檢索性能,但是會降低修改性能。當(dāng)減少索引時,會提高修改性能,降低檢索性能。因此,當(dāng)修改操作遠遠多于檢索操作時,不應(yīng)該創(chuàng)建索引。
4.索引的數(shù)據(jù)結(jié)構(gòu)
?
B-tree,B是balance,一般用于數(shù)據(jù)庫的索引。使用B-tree結(jié)構(gòu)可以顯著減少定位記錄時所經(jīng)歷的中間過程,從而加快存取速度。而B+tree是B-tree的一個變種,大名鼎鼎的MySQL就普遍使用B+tree實現(xiàn)其索引結(jié)構(gòu)。
插入(insert)操作:插入一個元素時,首先在B-tree中是否存在,如果不存在,即在葉子結(jié)點處結(jié)束,然后在葉子結(jié)點中插入該新的元素,注意:如果葉子結(jié)點空間足夠,這里需要向右移動該葉子結(jié)點中大于新插入關(guān)鍵字的元素,如果空間滿了以致沒有足夠的空間去添加新的元素,則將該結(jié)點進行“分裂”,將一半數(shù)量的關(guān)鍵字元素分裂到新的其相鄰右結(jié)點中,中間關(guān)鍵字元素上移到父結(jié)點中(當(dāng)然,如果父結(jié)點空間滿了,也同樣需要“分裂”操作),而且當(dāng)結(jié)點中關(guān)鍵元素向右移動了,相關(guān)的指針也需要向右移。如果在根結(jié)點插入新元素,空間滿了,則進行分裂操作,這樣原來的根結(jié)點中的中間關(guān)鍵字元素向上移動到新的根結(jié)點中,因此導(dǎo)致樹的高度增加一層。
刪除(delete)操作:首先查找B-tree中需刪除的元素,如果該元素在B-tree中存在,則將該元素在其結(jié)點中進行刪除,如果刪除該元素后,首先判斷該元素是否有左右孩子結(jié)點,如果有,則上移孩子結(jié)點中的某相近元素到父節(jié)點中,然后是移動之后的情況;如果沒有,直接刪除后,移動之后的情況.。刪除元素,移動相應(yīng)元素之后,如果某結(jié)點中元素數(shù)目小于ceil(m/2)-1,則需要看其某相鄰兄弟結(jié)點是否豐滿(結(jié)點中元素個數(shù)大于ceil(m/2)-1),如果豐滿,則向父節(jié)點借一個元素來滿足條件;如果其相鄰兄弟都剛脫貧,即借了之后其結(jié)點數(shù)目小于ceil(m/2)-1,則該結(jié)點與其相鄰的某一兄弟結(jié)點進行“合并”成一個結(jié)點,以此來滿足條件。
下面結(jié)合例子詳細講解mysql中索引的使用
索引是快速搜索的關(guān)鍵。MySQL索引的建立對于MySQL的高效運行是很重要的。下面介紹幾種常見的MySQL索引類型。
在數(shù)據(jù)庫表中,對字段建立索引可以大大提高查詢速度。假如我們創(chuàng)建了一個 mytable表:
?
[sql]?view plain?copy ??
我們隨機向里面插入了10000條記錄,其中有一條:5555, admin。
在查找username="admin"的記錄?
?
[sql]?view plain?copy ??
時,如果在username上已經(jīng)建立了索引,MySQL無須任何掃描,即準(zhǔn)確可找到該記錄。相反,MySQL會掃描所有記錄,即要查詢10000條記錄。
索引分單列索引和組合索引。單列索引,即一個索引只包含單個列,一個表可以有多個單列索引,但這不是組合索引。組合索引,即一個索包含多個列。
MySQL索引類型包括:
(1)普通索引
這是最基本的索引,它沒有任何限制。它有以下幾種創(chuàng)建方式:
◆創(chuàng)建索引
?
[sql]?view plain?copy ?如果是CHAR,VARCHAR類型,length可以小于字段實際長度;如果是BLOB和TEXT類型,必須指定 length,下同。
?
◆修改表結(jié)構(gòu)
?
[sql]?view plain?copy ??
◆創(chuàng)建表的時候直接指定
?
[sql]?view plain?copy ??
刪除索引的語法:
?
?
[sql]?view plain?copy ??
?
(2)唯一索引
它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。它有以下幾種創(chuàng)建方式:
◆創(chuàng)建索引
?
[sql]?view plain?copy ??
◆修改表結(jié)構(gòu)
?
[sql]?view plain?copy ??
◆創(chuàng)建表的時候直接指定
?
[sql]?view plain?copy ??
(3)主鍵索引
它是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創(chuàng)建主鍵索引:
?
[sql]?view plain?copy ??
當(dāng)然也可以用 ALTER 命令。記住:一個表只能有一個主鍵。
(4)組合索引
為了形象地對比單列索引和組合索引,為表添加多個字段:
?
[sql]?view plain?copy ??
為了進一步榨取MySQL的效率,就要考慮建立組合索引。就是將 name, city, age建到一個索引里:
?
[sql]?view plain?copy ??
建表時,usernname長度為 16,這里用
10。這是因為一般情況下名字的長度不會超過10,這樣會加速索引查詢速度,還會減少索引文件的大小,提高INSERT的更新速度。
如果分別在
usernname,city,age上建立單列索引,讓該表有3個單列索引,查詢時和上述的組合索引效率也會大不一樣,遠遠低于我們的組合索引。雖然此時有了三個索引,但MySQL只能用到其中的那個它認為似乎是最有效率的單列索引。
建立這樣的組合索引,其實是相當(dāng)于分別建立了下面三組組合索引:
usernname,city,age usernname,city usernname 為什么沒有
city,age這樣的組合索引呢?這是因為MySQL組合索引“最左前綴”的結(jié)果。簡單的理解就是只從最左面的開始組合。并不是只要包含這三列的查詢都會用到該組合索引,下面的幾個SQL就會用到這個組合索引:
?
[sql]?view plain?copy ??
?
而下面幾個則不會用到:
?
?
[sql]?view plain?copy ??
(5)建立索引的時機
到這里我們已經(jīng)學(xué)會了建立索引,那么我們需要在什么情況下建立索引呢?一般來說,在WHERE和JOIN中出現(xiàn)的列需要建立索引,但也不完全如此,因為MySQL只對<,<=,=,>,>=,BETWEEN,IN,以及某些時候的LIKE才會使用索引。例如:
?
[sql]?view plain?copy ??
此時就需要對city和age建立索引,由于mytable表的userame也出現(xiàn)在了JOIN子句中,也有對它建立索引的必要。
剛才提到只有某些時候的LIKE才需建立索引。因為在以通配符%和_開頭作查詢時,MySQL不會使用索引。例如下句會使用索引:
?
[sql]?view plain?copy ??
而下句就不會使用:
?
[sql]?view plain?copy ??
因此,在使用LIKE時應(yīng)注意以上的區(qū)別。
(6)索引的不足之處
上面都在說使用索引的好處,但過多的使用索引將會造成濫用。因此索引也會有它的缺點:
◆雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對表進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數(shù)據(jù),還要保存一下索引文件。
◆建立索引會占用磁盤空間的索引文件。一般情況這個問題不太嚴(yán)重,但如果你在一個大表上創(chuàng)建了多種組合索引,索引文件的會膨脹很快。
索引只是提高效率的一個因素,如果你的MySQL有大數(shù)據(jù)量的表,就需要花時間研究建立最優(yōu)秀的索引,或優(yōu)化查詢語句。
(7)使用索引的注意事項
使用索引時,有以下一些技巧和注意事項:
◆索引不會包含有NULL值的列
只要列中包含有NULL值都將不會被包含在索引中,復(fù)合索引中只要有一列含有NULL值,那么這一列對于此復(fù)合索引就是無效的。所以我們在數(shù)據(jù)庫設(shè)計時不要讓字段的默認值為NULL。
◆使用短索引
對串列進行索引,如果可能應(yīng)該指定一個前綴長度。例如,如果有一個CHAR(255)的列,如果在前10個或20個字符內(nèi),多數(shù)值是惟一的,那么就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節(jié)省磁盤空間和I/O操作。
◆索引列排序
MySQL查詢只使用一個索引,因此如果where子句中已經(jīng)使用了索引的話,那么order
by中的列是不會使用索引的。因此數(shù)據(jù)庫默認排序可以符合要求的情況下不要使用排序操作;盡量不要包含多個列的排序,如果需要最好給這些列創(chuàng)建復(fù)合索引。
◆like語句操作
一般情況下不鼓勵使用like操作,如果非使用不可,如何使用也是一個問題。like “%aaa%” 不會使用索引而like
“aaa%”可以使用索引。
◆不要在列上進行運算
?
[sql]?view plain?copy ?將在每個行上進行運算,這將導(dǎo)致索引失效而進行全表掃描,因此我們可以改成
?
?
[sql]?view plain?copy ??
◆不使用NOT IN和<>操作
原文轉(zhuǎn)載:http://blog.csdn.net/s592652578/article/details/52836559?locationNum=3&fps=1
轉(zhuǎn)載于:https://www.cnblogs.com/Allen0910/p/6744734.html
總結(jié)
- 上一篇: 【Java单例模式】Java单例模式之懒
- 下一篇: Mac系统安装nginx+rtmp模块