淺談數據庫索引

1.什么是索引

?

數據庫索引好比是一本書前面的目錄,能加快數據庫的查詢速度。

例如這樣一個查詢:select * from table1 where id=44。如果沒有索引,必須遍歷整個表,直到ID等于44的這一行被找到為止;有了索引之后(必須是在ID這一列上建立的索引),直接在索引里面找 44(也就是在ID這一列找),就可以得知這一行的位置,也就是找到了這一行。可見,索引是用來定位的。

索引分為聚簇索引和非聚簇索引兩種,聚簇索引 是按照數據存放的物理位置為順序的,而非聚簇索引就不一樣了;聚簇索引能提高多行檢索的速度,而非聚簇索引對于單行的檢索很快。

建立索引的目的是加快對表中記錄的查找或排序。
為表設置索引要付出代價的:一是增加了數據庫的存儲空間,二是在插入和修改數據時要花費較多的時間(因為索引也要隨之變動)。

2.為什么要創建索引

?

創建索引可以大大提高系統的性能。

第一,通過創建唯一性索引,可以保證數據庫表中每一行數據的唯一性。

第二,可以大大加快數據的檢索速度,這也是創建索引的最主要的原因。

第三,可以加速表和表之間的連接,特別是在實現數據的參考完整性方面特別有意義。

第四,在使用分組和排序子句進行數據檢索時,同樣可以顯著減少查詢中分組和排序的時間。

第五,通過使用索引,可以在查詢的過程中,使用優化隱藏器,提高系統的性能。

也許會有人要問:增加索引有如此多的優點,為什么不對表中的每一個列創建一個索引呢?因為,增加索引也有許多不利的方面。

第一,創建索引和維護索引要耗費時間,這種時間隨著數據量的增加而增加。

第二,索引需要占物理空間,除了數據表占數據空間之外,每一個索引還要占一定的物理空間,如果要建立聚簇索引,那么需要的空間就會更大。

第三,當對表中的數據進行增加、刪除和修改的時候,索引也要動態的維護,這樣就降低了數據的維護速度。

3.在哪建索引

?

索引是建立在數據庫表中的某些列的上面。在創建索引的時候,應該考慮在哪些列上可以創建索引,在哪些列上不能創建索引。一般來說,應該在這些列上創建索引:

1.在經常需要搜索的列上,可以加快搜索的速度;

2.在作為主鍵的列上,強制該列的唯一性和組織表中數據的排列結構;

3.在經常用在連接的列上,這些列主要是一些外鍵,可以加快連接的速度;在經常需要根據范圍進行搜索的列上創建索引,因為索引已經排序,其指定的范圍是連續的;

4.在經常需要排序的列上創建索引,因為索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;

5.在經常使用在WHERE子句中的列上面創建索引,加快條件的判斷速度。

同樣,對于有些列不應該創建索引。一般來說,不應該創建索引的的這些列具有下列特點:
第一,對于那些在查詢中很少使用或者參考的列不應該創建索引。這是因為,既然這些列很少使用到,因此有索引或者無索引,并不能提高查詢速度。相反,由于增加了索引,反而降低了系統的維護速度和增大了空間需求。

第二,對于那些只有很少數據值的列也不應該增加索引。這是因為,由于這些列的取值很少,例如人事表的性別列,在查詢的結果中,結果集的數據行占了表中數據行的很大比例,即需要在表中搜索的數據行的比例很大。增加索引,并不能明顯加快檢索速度。

第三,對于那些定義為text, image和bit數據類型的列不應該增加索引。這是因為,這些列的數據量要么相當大,要么取值很少,不利于使用索引。

第四,當修改性能遠遠大于檢索性能時,不應該創建索引。這是因為,修改性能和檢索性能是互相矛盾的。當增加索引時,會提高檢索性能,但是會降低修改性能。當減少索引時,會提高修改性能,降低檢索性能。因此,當修改操作遠遠多于檢索操作時,不應該創建索引。

4.索引的數據結構

?

B-tree,B是balance,一般用于數據庫的索引。使用B-tree結構可以顯著減少定位記錄時所經歷的中間過程,從而加快存取速度。而B+tree是B-tree的一個變種,大名鼎鼎的MySQL就普遍使用B+tree實現其索引結構。

插入(insert)操作:插入一個元素時,首先在B-tree中是否存在,如果不存在,即在葉子結點處結束,然后在葉子結點中插入該新的元素,注意:如果葉子結點空間足夠,這里需要向右移動該葉子結點中大于新插入關鍵字的元素,如果空間滿了以致沒有足夠的空間去添加新的元素,則將該結點進行“分裂”,將一半數量的關鍵字元素分裂到新的其相鄰右結點中,中間關鍵字元素上移到父結點中(當然,如果父結點空間滿了,也同樣需要“分裂”操作),而且當結點中關鍵元素向右移動了,相關的指針也需要向右移。如果在根結點插入新元素,空間滿了,則進行分裂操作,這樣原來的根結點中的中間關鍵字元素向上移動到新的根結點中,因此導致樹的高度增加一層。

刪除(delete)操作:首先查找B-tree中需刪除的元素,如果該元素在B-tree中存在,則將該元素在其結點中進行刪除,如果刪除該元素后,首先判斷該元素是否有左右孩子結點,如果有,則上移孩子結點中的某相近元素到父節點中,然后是移動之后的情況;如果沒有,直接刪除后,移動之后的情況.。刪除元素,移動相應元素之后,如果某結點中元素數目小于ceil(m/2)-1,則需要看其某相鄰兄弟結點是否豐滿(結點中元素個數大于ceil(m/2)-1),如果豐滿,則向父節點借一個元素來滿足條件;如果其相鄰兄弟都剛脫貧,即借了之后其結點數目小于ceil(m/2)-1,則該結點與其相鄰的某一兄弟結點進行“合并”成一個結點,以此來滿足條件。


下面結合例子詳細講解mysql中索引的使用

索引是快速搜索的關鍵。MySQL索引的建立對于MySQL的高效運行是很重要的。下面介紹幾種常見的MySQL索引類型。

在數據庫表中,對字段建立索引可以大大提高查詢速度。假如我們創建了一個 mytable表:

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. CREATE?TABLE?mytable(?ID?INT?NOT?NULL,?username?VARCHAR(16)?NOT?NULL??
  2. );??

?

我們隨機向里面插入了10000條記錄,其中有一條:5555, admin。

在查找username="admin"的記錄?

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. SELECT?*?FROM?mytable?WHERE??
  2. username='admin';??

?

時,如果在username上已經建立了索引,MySQL無須任何掃描,即準確可找到該記錄。相反,MySQL會掃描所有記錄,即要查詢10000條記錄。

索引分單列索引和組合索引。單列索引,即一個索引只包含單個列,一個表可以有多個單列索引,但這不是組合索引。組合索引,即一個索包含多個列。

MySQL索引類型包括:

(1)普通索引

這是最基本的索引,它沒有任何限制。它有以下幾種創建方式:

◆創建索引

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. CREATE?INDEX?indexName?ON?mytable(username(length));??

如果是CHAR,VARCHAR類型,length可以小于字段實際長度;如果是BLOB和TEXT類型,必須指定 length,下同。

?

◆修改表結構

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. ALTER?mytable?ADD?INDEX?[indexName]?ON?(username(length))??

?

◆創建表的時候直接指定

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. CREATE?TABLE?mytable(?ID?INT?NOT?NULL,?username?VARCHAR(16)?NOT?NULL,??
  2. ??
  3. INDEX?[indexName]?(username(length))?);???

?

刪除索引的語法:

?

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. DROP?INDEX?[indexName]?ON?mytable;??

?

?

(2)唯一索引

它與前面的普通索引類似,不同的就是:索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。它有以下幾種創建方式:

◆創建索引

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. CREATE?UNIQUE?INDEX?indexName?ON?mytable(username(length))??

?

◆修改表結構

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. ALTER?mytable?ADD?UNIQUE?[indexName]?ON?(username(length))??

?

◆創建表的時候直接指定

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. CREATE?TABLE?mytable(?ID?INT?NOT?NULL,?username?VARCHAR(16)?NOT?NULL,??
  2. UNIQUE?[indexName]?(username(length))?);??

?

(3)主鍵索引

它是一種特殊的唯一索引,不允許有空值。一般是在建表的時候同時創建主鍵索引:

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. CREATE?TABLE?mytable(?ID?INT?NOT?NULL,?username?VARCHAR(16)?NOT?NULL,??
  2. PRIMARY?KEY(ID)?);???

?

當然也可以用 ALTER 命令。記住:一個表只能有一個主鍵。

(4)組合索引

為了形象地對比單列索引和組合索引,為表添加多個字段:

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. CREATE?TABLE?mytable(?ID?INT?NOT?NULL,?username?VARCHAR(16)?NOT?NULL,??
  2. city?VARCHAR(50)?NOT?NULL,?age?INT?NOT?NULL?);??

?

為了進一步榨取MySQL的效率,就要考慮建立組合索引。就是將 name, city, age建到一個索引里:

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. ALTER?TABLE?mytable?ADD?INDEX?name_city_age?(name(10),city,age);??

?

建表時,usernname長度為 16,這里用
10。這是因為一般情況下名字的長度不會超過10,這樣會加速索引查詢速度,還會減少索引文件的大小,提高INSERT的更新速度。

如果分別在
usernname,city,age上建立單列索引,讓該表有3個單列索引,查詢時和上述的組合索引效率也會大不一樣,遠遠低于我們的組合索引。雖然此時有了三個索引,但MySQL只能用到其中的那個它認為似乎是最有效率的單列索引。

建立這樣的組合索引,其實是相當于分別建立了下面三組組合索引:

usernname,city,age usernname,city usernname 為什么沒有
city,age這樣的組合索引呢?這是因為MySQL組合索引“最左前綴”的結果。簡單的理解就是只從最左面的開始組合。并不是只要包含這三列的查詢都會用到該組合索引,下面的幾個SQL就會用到這個組合索引:

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. SELECT?*?FROM?mytable?WHREE?username="admin"?AND?city="鄭州"?SELECT?*?FROM??
  2. ??
  3. mytable?WHREE?username="admin"???

?

?

而下面幾個則不會用到:

?

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. SELECT?*?FROM?mytable?WHREE?age=20?AND?city="鄭州"?SELECT?*?FROM?mytable?WHREE??
  2. city="鄭州"??

?

(5)建立索引的時機

到這里我們已經學會了建立索引,那么我們需要在什么情況下建立索引呢?一般來說,在WHERE和JOIN中出現的列需要建立索引,但也不完全如此,因為MySQL只對<,<=,=,>,>=,BETWEEN,IN,以及某些時候的LIKE才會使用索引。例如:

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. SELECT?t.Name?FROM?mytable?t?LEFT?JOIN?mytable?m?ON?t.Name=m.username??
  2. WHERE?m.age=20?AND?m.city='鄭州'??

?

此時就需要對city和age建立索引,由于mytable表的userame也出現在了JOIN子句中,也有對它建立索引的必要。

剛才提到只有某些時候的LIKE才需建立索引。因為在以通配符%和_開頭作查詢時,MySQL不會使用索引。例如下句會使用索引:

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. SELECT?*?FROM?mytable?WHERE?username?like'admin%'???

?

而下句就不會使用:

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. SELECT?*?FROM?mytable?WHEREt?Name?like'%admin'???

?

因此,在使用LIKE時應注意以上的區別。

(6)索引的不足之處

上面都在說使用索引的好處,但過多的使用索引將會造成濫用。因此索引也會有它的缺點:

◆雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對表進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數據,還要保存一下索引文件。

◆建立索引會占用磁盤空間的索引文件。一般情況這個問題不太嚴重,但如果你在一個大表上創建了多種組合索引,索引文件的會膨脹很快。

索引只是提高效率的一個因素,如果你的MySQL有大數據量的表,就需要花時間研究建立最優秀的索引,或優化查詢語句。

(7)使用索引的注意事項

使用索引時,有以下一些技巧和注意事項:

◆索引不會包含有NULL值的列

只要列中包含有NULL值都將不會被包含在索引中,復合索引中只要有一列含有NULL值,那么這一列對于此復合索引就是無效的。所以我們在數據庫設計時不要讓字段的默認值為NULL。

◆使用短索引

對串列進行索引,如果可能應該指定一個前綴長度。例如,如果有一個CHAR(255)的列,如果在前10個或20個字符內,多數值是惟一的,那么就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節省磁盤空間和I/O操作。

◆索引列排序

MySQL查詢只使用一個索引,因此如果where子句中已經使用了索引的話,那么order
by中的列是不會使用索引的。因此數據庫默認排序可以符合要求的情況下不要使用排序操作;盡量不要包含多個列的排序,如果需要最好給這些列創建復合索引。

◆like語句操作

一般情況下不鼓勵使用like操作,如果非使用不可,如何使用也是一個問題。like “%aaa%” 不會使用索引而like
“aaa%”可以使用索引。

◆不要在列上進行運算

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. select?*?from?users?where?YEAR(adddate)<2007;??

將在每個行上進行運算,這將導致索引失效而進行全表掃描,因此我們可以改成

?

?

[sql]?view plain?copy
?在CODE上查看代碼片派生到我的代碼片
  1. select?*?from?users?where?adddate<‘2007-01-01’;??

?

◆不使用NOT IN和<>操作

原文轉載:http://blog.csdn.net/s592652578/article/details/52836559?locationNum=3&fps=1

轉載于:https://www.cnblogs.com/Allen0910/p/6744734.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455931.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455931.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455931.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

iphone屏幕突然變暗_如果你的iPhone屏幕突然變暗,可以這樣解決

??如果在使用 iPhone 的過程中&#xff0c;屏幕忽然變暗&#xff0c;可能有如下原因&#xff1a;開啟了“亮度自動調節”功能在 iPhone 中有一項“亮度自動調節”的功能&#xff0c;此功能是根據設備周圍的光線條件來調整亮度級別&#xff1a;在光線較暗的地方&#xff0c;傳…

宏塊與宏塊對(附圖)

宏塊與宏塊對&#xff08;附圖&#xff09; 假設 A、B 是上下相鄰的兩個 MB&#xff1a;在非宏塊對的情況下&#xff1a;A、B宏塊序號不連續&#xff0c;相差圖像一行宏塊個數。即按光柵掃描順序編號。在幀宏塊對的情況下&#xff1a;A、B宏塊序號連續&#xff0c;即按鋸齒掃描…

農業部部署農業大數據發展工作 評:對農業現代化很重要

據中國鄉村之聲《三農中國》報道&#xff0c;近日&#xff0c;農業部近日印發了《關于推進農業農村大數據發展的實施意見》&#xff0c;全面部署農業農村大數據發展工作。 《意見》明確了農業農村大數據發展和應用的五大基礎性工作和十一個重點領域&#xff0c;包括夯實國家農業…

HTML中的鏈接

HTML鏈接 <a>標簽可以在網頁上定義一個鏈接地址&#xff0c;通過href屬性定義跳轉的地址&#xff0c;通過title屬性定義鼠標懸停時彈出的提示文字框。 <a href"#"></a> <!-- # 表示鏈接到頁面頂部 --> <a href"http://www.itxdl.…

【MySQL】Linux端-實現Mysql數據定時自動備份

Linux端-實現Mysql數據定時自動備份 創建存放備份 sql 的文件夾 備份數據盡量存放在Linux單獨掛載的磁盤上&#xff0c;保證數據可靠性。磁盤建議使用EXT4分區格式。 [rootlocalhost ~]# mkdir /sk/mysqlBackup測試命令行備份數據庫 [rootlocalhost ~]# /usr/bin/mysqldump --o…

視頻測試序列的下載地址

1、http://www.tkn.tu-berlin.de/research/vid/&#xff08;此網站已經移走&#xff0c;正在尋找。&#xff09; CIF&#xff1a; Akiyo、Bridge (far) 、Bridge (close) 、Bus 、Container 、Coastguard 、Flower 、Football 、Foreman 、Hall 、Highway 、Mobile & Cal…

xtrabackup遷移單獨一張INNODB表

轉載于:https://www.cnblogs.com/llguanli/p/6746130.html

c語言有趣代碼_為什么C語言永遠不會過時?

直至今天還有人在喊著C語言都過時的語言了&#xff0c;還有什么值得去學的&#xff0c;看現在的python&#xff0c;php等語言現在用起來多簡單&#xff0c;誰還去學習老掉牙的C語言&#xff0c;事實真的是這樣的嗎&#xff1f;筆者作為專門下載了這兩種語言的底層源碼。由于篇幅…

Pokemon Go將在日本發布 網絡安全公司呼吁防范虛假軟件

據《每日新聞》報道&#xff0c;手游《Pokemon Go》(精靈寶可夢Go)在海外人氣爆棚&#xff0c;日本國內也有望近日發布。日本網絡安全公司呼吁&#xff0c;在正式發布前需防范虛假游戲軟件。 美國英特爾集團邁克菲公司&#xff08;東京都澀谷區&#xff09;表示&#xff0c;《P…

【接口文檔】Django restful framework中自動生成API文檔

Django restful framework中自動生成API文檔 一、Swagger概述 1.引言 當接口開發完成&#xff0c;緊接著需要編寫接口文檔。傳統的接口文檔使用Word編寫&#xff0c;or一些接口文檔管理平臺進行編寫&#xff0c;但此類接口文檔維護更新比較麻煩&#xff0c;每次接口有變更&am…

HTML中的列表

HTML列表 無序列表 在網頁上定義一個無編號的內容列表可以用<ul>、<li>配合使用來實現&#xff0c;代碼如下&#xff1a; <ul><li>列表文字一</li><li>列表文字二</li><li>列表文字三</li> </ul>在網頁上生成的列…

【ujson】pip安裝ujson報錯: error:Microsoft Visual C++ 14.0 is required

在win10上pip安裝ujson報錯 在使用pip安裝依賴包ujson時&#xff0c;遇到了問題&#xff0c;如下&#xff1a; building ujson extension error: Microsoft Visual C 14.0 is required. Get it with "Microsoft Visual C Build Tools": http://landinghub.visua…

HTML中的表格

HTML表格 table常用標簽 1、table標簽&#xff1a;聲明一個表格 2、tr標簽&#xff1a;定義表格中的一行 3、td和th標簽&#xff1a;定義一行中的一個單元格&#xff0c;td代表普通單元格&#xff0c;th表示表頭單元格 table常用屬性&#xff1a; 1、border 定義表格的…

CS224n筆記13 卷積神經網絡

為什么80%的碼農都做不了架構師&#xff1f;>>> 本文由碼農場同步&#xff0c;最新版本請查看原文&#xff1a;http://www.hankcs.com/nlp/cs224n-convolutional-neural-networks.html 補充了NLP中相對冷門的CNN&#xff0c;談了談調參與發論文的潛規則。從RNN到CN…

android tcp socket框架_socket網絡編程知識梳理,讓你學會造輪子的能力

在前面幾篇中&#xff0c;我給大家介紹了socket的相關知識&#xff0c;也給出了詳細的代碼&#xff0c;從socket的基本介紹&#xff0c;到IO多路復用&#xff0c;以及粘包拆包&#xff0c;最后到心跳包問題。總的來說大概都把socket網絡編程中能碰見的問題都講了&#xff0c;但…

264分析兩大利器:264VISA和Elecard StreamEye Tools

學了264有將近3個月有余&#xff0c;好多時候都在學習老畢的書和反復看JM86的代碼&#xff0c;最近才找到264分析兩大利器&#xff1a;264VISA和Elecard StreamEye Tools。不由得感嘆&#xff0c;恨不逢同時。 簡單的說下這兩個軟件&#xff1a; 264visa 強力的h264實時分析工具…

【解決】Django錯誤(1146,Table 'xxxx.django_session' doesn't exist)

報錯 解決辦法&#xff0c;settings.py中取消這行注釋&#xff0c;講session放緩存中 沒執行遷移的話&#xff0c;可能是debugtoolbar 把內容存儲在session中了 session最后也是放在redis里面的

QTP提供的編程接口實現對QTP操作

我們可以通過調用 Automation Object Model 里的對象接口 ,來實現對QTP 的操作,如打開 /運行腳本等動作Automation object model 的對象結構圖如下 (摘自QTP 參考手冊 )最新內容請見作者的GitHub頁&#xff1a;http://qaseven.github.io/

正態性檢驗ks和sw區別_非參數檢驗思路總結,清晰理解就靠它了!

1. 何時使用非參數檢驗或許你還沒有理解什么是參數檢驗、非參數檢驗&#xff0c;但一定曾在無意之中使用過它們。如我們常用的方差分析、T檢驗&#xff0c;都屬于參數檢驗。參數檢驗&#xff0c;就是假定數據服從某種分布&#xff0c;通過樣本信息對總體參數進行檢驗。因而在分…

【Python基礎入門系列】第01天:環境搭建

其實 Python 已經是一個很老的編程語言了&#xff0c;到現在&#xff08;2019年&#xff09; Python 已經高齡 28 歲&#xff0c;比很多程序員的年齡都大。現在之所以這么流行和社區、人工智能的發展&#xff0c;有很大的關系。 千里之行始于足下&#xff0c;今天我們先來學習…