【面向校招】數(shù)據(jù)庫 —— Mysql索引

1. 索引是什么?

索引是一種特殊的文件(InnoDB數(shù)據(jù)表上的索引是表空間的一個組成部分)纠炮,它們包含著對數(shù)據(jù)表里所有記錄的引用指針孝宗。

索引是一種數(shù)據(jù)結構问潭。數(shù)據(jù)庫索引狡忙,是數(shù)據(jù)庫管理系統(tǒng)中一個排序的數(shù)據(jù)結構灾茁,以協(xié)助快速查詢北专、更新數(shù)據(jù)庫表中數(shù)據(jù)。索引的實現(xiàn)通常使用B樹及其變種B+樹驶睦。更通俗的說场航,索引是表的目錄,在查找內容之前可以先在目錄中查找索引位置适室,以此快速定位查詢數(shù)據(jù)蔬螟。對于索引旧巾,會保存在額外的文件中鲁猩,它是要占據(jù)物理空間的。

MySQL索引的建立對于MySQL的高效運行是很重要的隙券,索引可以大大提高MySQL的檢索速度娱仔。比如我們在查字典的時候,前面都有檢索的拼音和偏旁恩溅、筆畫等脚乡,然后找到對應字典頁碼,這樣然后就打開字典的頁數(shù)就可以知道我們要搜索的某一個key的全部值的信息了锌订。

2. 索引有哪些優(yōu)缺點啦辐?

索引的優(yōu)點

  • 當表中的數(shù)據(jù)量越來越大時芹关,索引對于性能的影響愈發(fā)重要侥衬。索引能夠輕易將查詢性能提高好幾個數(shù)量級,總的來說就是可以明顯的提高查詢效率怀樟。
  • 可以大大加快數(shù)據(jù)的檢索速度漂佩,這也是創(chuàng)建索引的最主要的原因征堪。
  • 通過使用索引佃蚜,可以在查詢的過程中,使用優(yōu)化隱藏器洲脂,提高系統(tǒng)的性能。
  • 通過創(chuàng)建唯一索引
  • 加快表與表之間的連接

索引的缺點

  • 時間方面:創(chuàng)建索引和維護索引要耗費時間一铅,具體地肮之,當對表中的數(shù)據(jù)進行增加、刪除和修改的時候暴凑,索引也要動態(tài)的維護,會降低增/改/刪的執(zhí)行效率嗦篱;
  • 空間方面:索引需要占物理空間灸促。

3. 哪些列上適合創(chuàng)建索引荒叼?創(chuàng)建索引有哪些開銷被廓?

經(jīng)常需要作為條件查詢的列上適合創(chuàng)建索引,并且該列上也必須有一定的區(qū)分度。

創(chuàng)建索引需要維護挎春,在插入數(shù)據(jù)的時候會重新維護各個索引樹(數(shù)據(jù)頁的分裂與合并),對性能造成影響

4. 索引這么多優(yōu)點痴突,為什么不對表中的每一個列創(chuàng)建一個索引呢搂蜓?

  1. 當對表中的數(shù)據(jù)進行增加、刪除和修改的時候辽装,索引也要動態(tài)的維護帮碰,這樣就降低了數(shù)據(jù)的維護速度。
  2. 索引需要占物理空間拾积,除了數(shù)據(jù)表占數(shù)據(jù)空間之外,每一個索引還要占一定的物理空間傻唾,如果要建立聚簇索引抱既,那么需要的空間就會更大。
  3. 創(chuàng)建索引和維護索引要耗費時間拭卿,這種時間隨著數(shù)據(jù)量的增加而增加。

5. MySQL有哪幾種索引類型呐馆?

1、從存儲結構上來劃分:BTree索引(B-Tree或B+Tree索引),Hash索引扛或,full-index全文索引,R-Tree索引柳爽。這里所描述的是索引存儲時保存的形式俩功,

2洽腺、從應用層次來分:普通索引炼彪,唯一索引萄唇,復合索引泛源。

  • 普通索引:即一個索引只包含單個列伐蒂,一個表可以有多個單列索引
  • 唯一索引:索引列的值必須唯一部逮,但允許有空值
  • 復合索引:多列值組成一個索引,專門用于組合搜索,其效率大于索引合并

3秦踪、根據(jù)中數(shù)據(jù)的物理順序與鍵值的邏輯(索引)順序關系: 聚集索引,非聚集索引门岔。

  • 聚簇索引(聚集索引):并不是一種單獨的索引類型,而是一種數(shù)據(jù)存儲方式棋凳。具體細節(jié)取決于不同的實現(xiàn)蠢箩,InnoDB的聚簇索引其實就是在同一個結構中保存了B-Tree索引(技術上來說是B+Tree)和數(shù)據(jù)行邦马。
  • 非聚簇索引: 不是聚簇索引,就是非聚簇索引

6. 說一說索引的底層實現(xiàn)屁桑?

Hash索引

基于哈希表實現(xiàn)域携,只有精確匹配索引所有列的查詢才有效蒲凶,對于每一行數(shù)據(jù)气筋,存儲引擎都會對所有的索引列計算一個哈希碼(hash code),并且Hash索引將所有的哈希碼存儲在索引中旋圆,同時在索引表中保存指向每個數(shù)據(jù)行的指針宠默。

圖片來源:https://www.javazhiyin.com/40232.html

[圖片上傳失敗...(image-f8109c-1653141194846)]

B-Tree索引(MySQL使用B+Tree)

B-Tree能加快數(shù)據(jù)的訪問速度,因為存儲引擎不再需要進行全表掃描來獲取數(shù)據(jù)灵巧,數(shù)據(jù)分布在各個節(jié)點之中搀矫。

[圖片上傳失敗...(image-b502fc-1653141194846)]

B+Tree索引

是B-Tree的改進版本,同時也是數(shù)據(jù)庫索引索引所采用的存儲結構刻肄。數(shù)據(jù)都在葉子節(jié)點上瓤球,并且增加了順序訪問指針,每個葉子節(jié)點都指向相鄰的葉子節(jié)點的地址敏弃。相比B-Tree來說卦羡,進行范圍查找時只需要查找兩個節(jié)點,進行遍歷即可麦到。而B-Tree需要獲取所有節(jié)點绿饵,相比之下B+Tree效率更高。

B+tree性質:

  • n棵子tree的節(jié)點包含n個關鍵字瓶颠,不用來保存數(shù)據(jù)而是保存數(shù)據(jù)的索引拟赊。
  • 所有的葉子結點中包含了全部關鍵字的信息,及指向含這些關鍵字記錄的指針粹淋,且葉子結點本身依關鍵字的大小自小而大順序鏈接吸祟。
  • 所有的非終端結點可以看成是索引部分瑟慈,結點中僅含其子樹中的最大(或最小)關鍵字屋匕。
  • B+ 樹中封豪,數(shù)據(jù)對象的插入和刪除僅在葉節(jié)點上進行。
  • B+樹有2個頭指針炒瘟,一個是樹的根節(jié)點,一個是最小關鍵碼的葉節(jié)點第步。

[圖片上傳失敗...(image-a89abf-1653141194846)]

7. 為什么索引結構默認使用B+Tree疮装,而不是B-Tree,Hash粘都,二叉樹廓推,紅黑樹?

B-tree:因為B樹不管葉子節(jié)點還是非葉子節(jié)點翩隧,都會保存數(shù)據(jù)樊展,這樣導致在非葉子節(jié)點中能保存的指針數(shù)量變少(有些資料也稱為扇出),指針少的情況下要保存大量數(shù)據(jù)堆生,只能增加樹的高度专缠,導致IO操作變多,查詢性能變低淑仆;

B+tree: 從兩個方面來回答

  • B+樹的磁盤讀寫代價更低:B+樹的內部節(jié)點并沒有指向關鍵字具體信息的指針涝婉,因此其內部節(jié)點相對B樹更小,如果把所有同一內部節(jié)點的關鍵字存放在同一盤塊中蔗怠,那么盤塊所能容納的關鍵字數(shù)量也越多墩弯,一次性讀入內存的需要查找的關鍵字也就越多,相對IO讀寫次數(shù)就降低了渔工。
  • 由于B+樹的數(shù)據(jù)都存儲在葉子結點中桥温,分支結點均為索引,方便掃庫策治,只需要掃一遍葉子結點即可脓魏,但是B樹因為其分支結點同樣存儲著數(shù)據(jù)通惫,我們要找到具體的數(shù)據(jù),需要進行一次中序遍歷按序來掃履腋,所以B+樹更加適合在區(qū)間查詢的情況珊燎,所以通常B+樹用于數(shù)據(jù)庫索引。

Hash

  • 雖然可以快速定位晚吞,但是沒有順序谋国,IO復雜度高芦瘾;
  • 基于Hash表實現(xiàn),只有Memory存儲引擎顯式支持哈希索引 缅糟;
  • 適合等值查詢祷愉,如=二鳄、in()、<=>句占,不支持范圍查詢 纱烘;
  • 因為不是按照索引值順序存儲的祈餐,就不能像B+Tree索引一樣利用索引完成排序 ;
  • Hash索引在查詢等值時非撤簦快 蜒谤;
  • 因為Hash索引始終索引的所有列的全部內容鳍徽,所以不支持部分索引列的匹配查找 ;
  • 如果有大量重復鍵值得情況下绷杜,哈希索引的效率會很低鞭盟,因為存在哈希碰撞問題 。

二叉樹: 樹的高度不均勻筝野,不能自平衡遗座,查找效率跟數(shù)據(jù)有關(樹的高度)俊扳,并且IO代價高馋记。

紅黑樹: 樹的高度隨著數(shù)據(jù)量增加而增加梯醒,IO代價高腌紧。

不使用平衡二叉樹的原因如下

最大原因:深度太大(因為一個節(jié)點最多只有2個子節(jié)點)壁肋,一次查詢需要的I/O復雜度為O(lgN),而b+tree只需要O(log_mN),而其出度m非常大,其深度一般不會超過4 平衡二叉樹邏輯上很近的父子節(jié)點猫胁,物理上可能很遠弃秆,無法充分發(fā)揮磁盤順序讀和預讀的高效特性菠赚。

8. MyISAM和InnoDB實現(xiàn)BTree索引方式的區(qū)別

1)MyISAM

B+Tree葉節(jié)點的data域存放的是數(shù)據(jù)記錄的地址郑藏。在索引檢索的時候译秦,首先按照B+Tree搜索算法搜索索引击碗,如果指定的Key存在稍途,則取出其 data 域的值械拍,然后以 data 域的值為地址讀取相應的數(shù)據(jù)記錄装盯。這被稱為“非聚簇索引”埂奈。 索引文件和數(shù)據(jù)文件是分離的

2)InnoDB

  • InnoDB 的 B+Tree 索引分為主索引(聚集索引)和輔助索引(非聚集索引)账磺。一張表一定包含一個聚集索引構成的 B+ 樹以及若干輔助索引的構成的 B+ 樹。
  • 輔助索引的存在并不會影響聚集索引氏捞,因為聚集索引構成的 B+ 樹是數(shù)據(jù)實際存儲的形式液茎,而輔助索引只用于加速數(shù)據(jù)的查找捆等,所以一張表上往往有多個輔助索引以此來提升數(shù)據(jù)庫的性能续室。
  • 就很容易明白為什么不建議使用過長的字段作為主鍵猎贴,因為所有輔助索引都引用主索引她渴,過長的主索引會令輔助索引變得過大。再例如沉唠,用非單調的字段作為主鍵在InnoDB中不是個好主意满葛,因為InnoDB數(shù)據(jù)文件本身是一顆B+Tree嘀韧,非單調的主鍵會造成在插入新記錄時數(shù)據(jù)文件為了維持B+Tree的特性而頻繁的分裂調整,十分低效译蒂,而使用自增字段作為主鍵則是一個很好的選擇柔昼。

9. 主鍵索引和非主鍵索引

TYPE INDEX
id int id(primary key)
k int k
name varchar

假設有如上表結構, 那么建立起的索引結構如下圖

[圖片上傳失敗...(image-3adc58-1653141194846)]

從圖中看出, 根據(jù)葉子節(jié)點內容的不同, 索引類型分為主鍵索引和非主鍵索引.

  • 主鍵索引的葉子節(jié)點存儲的是整行數(shù)據(jù). 在InnoDB里, 主鍵索引也被稱為聚簇索引
  • 非主鍵索引的葉子節(jié)點存儲的是主鍵的值. 在InnoDB里, 非主鍵索引也被稱為二級索引 / 非聚簇索引

10. 講一講聚簇索引與非聚簇索引捕透?

在 InnoDB 里激率,索引B+ Tree的葉子節(jié)點存儲了整行數(shù)據(jù)的是主鍵索引勿决,也被稱之為聚簇索引低缩,即將數(shù)據(jù)存儲與索引放到了一塊咆繁,找到索引也就找到了數(shù)據(jù)顶籽。

而索引B+ Tree的葉子節(jié)點存儲了主鍵的值的是非主鍵索引礼饱,也被稱之為非聚簇索引镊绪、二級索引。

聚簇索引與非聚簇索引的區(qū)別:

  • 非聚集索引與聚集索引的區(qū)別在于非聚集索引的葉子節(jié)點不存儲表中的數(shù)據(jù)够颠,而是存儲該列對應的主鍵(行號)
  • 對于InnoDB來說履磨,想要查找數(shù)據(jù)我們還需要根據(jù)主鍵再去聚集索引中進行查找剃诅,這個再根據(jù)聚集索引查找數(shù)據(jù)的過程综苔,我們稱為回表。第一次索引一般是順序IO堡牡,回表的操作屬于隨機IO晤柄。需要回表的次數(shù)越多芥颈,即隨機IO次數(shù)越多赚抡,我們就越傾向于使用全表掃描 涂臣。
  • 通常情況下赁遗, 主鍵索引(聚簇索引)****查詢只會查一次岩四,而非主鍵索引(非聚簇索引)****需要回表查詢多次。當然材鹦,如果是覆蓋索引的話侠姑,查一次即可
  • 注意:MyISAM無論主鍵索引還是二級索引都是非聚簇索引莽红,而InnoDB的主鍵索引是聚簇索引安吁,二級索引是非聚簇索引。我們自己建的索引基本都是非聚簇索引网棍。

11. 非聚簇索引一定會回表查詢嗎滥玷?

不一定惑畴,這涉及到查詢語句所要求的字段是否全部命中了索引如贷,如果全部命中了索引杠袱,那么就不必再進行回表查詢窝稿。一個索引包含(覆蓋)所有需要查詢字段的值伴榔,被稱之為"覆蓋索引"潮梯。

舉個簡單的例子秉馏,假設我們在員工表的年齡上建立了索引萝究,那么當進行select score from student where score > 90的查詢時锉罐,在索引的葉子節(jié)點上脓规,已經(jīng)包含了score 信息,不會再次進行回表查詢绢陌。

12. 聯(lián)合索引是什么脐湾?為什么需要注意聯(lián)合索引中的順序秤掌?

MySQL可以使用多個字段同時建立一個索引闻鉴,叫做聯(lián)合索引椒拗。在聯(lián)合索引中获黔,如果想要命中索引玷氏,需要按照建立索引時的字段順序挨個使用盏触,否則無法命中索引赞辩。

具體原因為:

MySQL使用索引時需要索引有序辨嗽,假設現(xiàn)在建立了"name糟需,age,school"的聯(lián)合索引武花,那么索引的排序為: 先按照name排序体箕,如果name相同干旁,則按照age排序争群,如果age的值也相等换薄,則按照school進行排序轻要。

當進行查詢時冲泥,此時索引僅僅按照name嚴格有序凡恍,因此必須首先使用name字段進行等值查詢嚼酝,之后對于匹配到的列而言,其按照age字段嚴格有序钧舌,此時可以使用age字段用做索引查找洼冻,以此類推撞牢。因此在建立聯(lián)合索引的時候應該注意索引列的順序普泡,一般情況下,將查詢需求頻繁或者字段選擇性高的列放在前面垒酬。此外可以根據(jù)特例的查詢或者表結構進行單獨的調整勘究。

13. 回表

當執(zhí)行 SELECT * FROM t WHERE id = 500 時, 即主鍵查詢方式, 則需要搜索ID這顆B+樹; 當執(zhí)行 SELECT * FROM t WHERE k = 5 時, 即普通索引查詢方式, 則先在k這棵樹查找到主鍵的值, 再從ID這棵樹中查找到對應的行.

當我們執(zhí)行SQL搜索數(shù)據(jù)時, 如果需要先從非主鍵索引中查詢到主鍵的值, 再從主鍵索引中查詢到對應的數(shù)據(jù), 這個過程就被稱為回表. 所以應該盡量使用主鍵查詢.

14. 索引維護 (頁分裂與頁合并)

B+樹為了有序性, 需要對插入和刪除數(shù)據(jù)時做出對應的維護. 當插入數(shù)據(jù)時, 如在上圖中插入ID=400的數(shù)據(jù), 那么從邏輯上來說, 需要移動后面的數(shù)據(jù), 空出位置.

若此時R5所在數(shù)據(jù)頁滿了, 則需要申請一個新的數(shù)據(jù)頁, 然后移動部分數(shù)據(jù)到新數(shù)據(jù)頁中, 這個過程被稱為頁分裂. 頁分裂影響了數(shù)據(jù)頁的空間利用率, 而且在分裂過程中, 性能也會有所影響.

若相鄰兩個數(shù)據(jù)頁因為刪除導致利用率很低后, 那么會將這兩個數(shù)據(jù)頁的數(shù)據(jù)合并到一個數(shù)據(jù)頁中, 這個過程被稱為頁合并. 即頁分裂的逆過程.

15. 覆蓋索引

如果執(zhí)行了語句 SELECT id FROM t WHERE k between 3 and 5 時, 只需要查詢 id 的值, 而 id 已經(jīng)在 k 的索引樹上, 所以不需要再回表去查詢整行, 直接返回查詢結果, 索引 k 已經(jīng)覆蓋了這條SQL查詢的需求, 被稱為 覆蓋索引. 覆蓋索引能夠減少樹的搜索次數(shù), 不需要再次回表查詢整行, 所以是一個常用的性能優(yōu)化手段.

16. 講一講MySQL的最左前綴原則?

最左前綴原則 就是利用索引列中最左的字段優(yōu)先進行匹配

最左前綴原則就是最左優(yōu)先缅阳,在創(chuàng)建多列索引時十办,要根據(jù)業(yè)務需求向族,where子句中使用最頻繁的一列放在最左邊件相。

mysql會一直向右匹配直到遇到范圍查詢(>夜矗、<侯养、between逛揩、like)就停止匹配辩稽。

例如:b = 2 如果建立(a,b)順序的索引逞泄,是匹配不到(a,b)索引的喷众;但是如果查詢條件是a = 1 and b = 2,就可以到千,因為優(yōu)化器會自動調整a,b的順序憔四。

比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引了赵,d是用不到索引的柿汛,因為c字段是一個范圍查詢络断,它之后的字段會停止匹配妓羊。如果建立(a,b,d,c)的索引則都可以用到躁绸,a,b,d的順序可以任意調整净刮。

=和in可以亂序淹父,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序暑认,mysql的查詢優(yōu)化器會幫你優(yōu)化成索引可以識別的形式蘸际。

最左匹配原則的原理

MySQL中的索引可以以一定順序引用多列粮彤,這種索引叫作聯(lián)合索引.最左匹配原則都是針對聯(lián)合索引來說的

  • 我們都知道索引的底層是一顆B+樹导坟,那么聯(lián)合索引當然還是一顆B+樹惫周,只不過聯(lián)合索引的健值數(shù)量不是一個,而是多個闯两。構建一顆B+樹只能根據(jù)一個值來構建褥伴,因此數(shù)據(jù)庫依據(jù)聯(lián)合索引最左的字段來構建B+樹。 例子:假如創(chuàng)建一個(a,b)的聯(lián)合索引漾狼,那么它的索引樹是這樣的可以看到a的值是有順序的重慢,1,1逊躁,2,2稽煤,3核芽,3,而b的值是沒有順序的1酵熙,2轧简,1,4匾二,1哮独,2。所以b = 2這種查詢條件沒有辦法利用索引察藐,因為聯(lián)合索引首先是按a排序的皮璧,b是無序的。

同時我們還可以發(fā)現(xiàn)在a值相等的情況下分飞,b值又是按順序排列的悴务,但是這種順序是相對的。所以最左匹配原則遇上范圍查詢就會停止譬猫,剩下的字段都無法使用索引讯檐。例如a = 1 and b = 2 a,b字段都可以使用索引,因為在a值確定的情況下b是相對有序的染服,而a>1and b=2裂垦,a字段可以匹配上索引,但b值不可以肌索,因為a的值是一個范圍蕉拢,在這個范圍中b是無序的。

優(yōu)點:最左前綴原則的利用也可以顯著提高查詢效率诚亚,是常見的MySQL性能優(yōu)化手段晕换。

17. 講一講前綴索引?

在對字符串創(chuàng)建索引, 如INDEX(name)中, 若字符串非常大, 那么響應的空間使用和維護開銷也非常大, 就可以使用字符串從左開始的部分字符創(chuàng)建索引(把很長字段的前面的公共部分作為一個索引站宗,就會產生超級加倍的效果, 減少空間和維護的成本, 但是也會降低索引的選擇性闸准。但是,我們需要注意梢灭,order by不支持前綴索引 夷家。

索引的選擇性指的是 : 不重復的索引值和數(shù)據(jù)表的記錄總數(shù)(#T)的比值, 范圍為 1/#T 到 1 之間, 索引選擇性越高則查詢效率越高. 對于BLOB, TEXT, VARCHAR等類型的列, 必須使用前綴索引, MySQL不允許索引這些列的完整長度.

流程是:

  1. 先計算完整列的選擇性 SELECT COUNT(DISTINCT name)/COUNT(1) FROM t
  2. 在計算不同前綴長度N的選擇性 SELECT COUNT(DISCTINCT LEFT(name, N)) / COUNT(1) FROM t
  3. 看哪個N更靠近1, 進行索引的創(chuàng)建

18. 了解索引下推嗎蒸其?

對于SQL語句 SELECT * FROM t WHERE name LIKE '陳%' AND age = 10 , INDEX(name, age) 情況來說

在 MySQL5.6 之前沒有引入索引下推優(yōu)化時, 執(zhí)行流程如下圖, 在定位完name字段的索引后, 需要一條條進行回表查詢, 然后再判斷其他字段是否滿足條件.

[圖片上傳失敗...(image-4324e3-1653141194846)]

而 MySQL5.6 引入了索引下推優(yōu)化后, 可以在所有遍歷過程中, 對索引中包含的字段先進行判斷過濾, 然后再進行后續(xù)操作, 減少了回表次數(shù).

[圖片上傳失敗...(image-b4dbc3-1653141194846)]

19. 怎么查看MySQL語句有沒有用到索引?

通過explain库快,如以下例子:

EXPLAIN SELECT * FROM employees.titles WHERE emp_no='10001' AND title='Senior Engineer' AND from_date='1986-06-26';

id select_type table partitions type possible_keys key key_len ref filtered rows Extra
1 SIMPLE titles null const PRIMARY PRIMARY 59 const,const,const 10 1
  • id:在?個?的查詢語句中每個SELECT關鍵字都對應?個唯?的id 摸袁,如explain select * from s1 where id = (select id from s1 where name = 'egon1');第一個select的id是1,第二個select的id是2义屏。有時候會出現(xiàn)兩個select靠汁,但是id卻都是1,這是因為優(yōu)化器把子查詢變成了連接查詢 闽铐。
  • select_type:select關鍵字對應的那個查詢的類型蝶怔,如SIMPLE,PRIMARY,SUBQUERY,DEPENDENT,SNION 。
  • table:每個查詢對應的表名 兄墅。
  • type:type 字段比較重要, 它提供了判斷查詢是否高效的重要依據(jù)依據(jù). 通過 type 字段, 我們判斷此次查詢是 全表掃描 還是 索引掃描 等踢星。如const(主鍵索引或者唯一二級索引進行等值匹配的情況下),ref(普通的?級索引列與常量進?等值匹配),index(掃描全表索引的覆蓋索引) 。通常來說, 不同的 type 類型的性能關系如下:ALL < index < range ~ index_merge < ref < eq_ref < const < systemALL 類型因為是全表掃描, 因此在相同的查詢條件下, 它是速度最慢的.而 index 類型的查詢雖然不是全表掃描, 但是它掃描了所有的索引, 因此比 ALL 類型的稍快.
  • possible_key:查詢中可能用到的索引(可以把用不到的刪掉隙咸,降低優(yōu)化器的優(yōu)化時間) 斩狱。
  • key:此字段是 MySQL 在當前查詢時所真正使用到的索引。
  • filtered:查詢器預測滿足下一次查詢條件的百分比 扎瓶。
  • rows 也是一個重要的字段. MySQL 查詢優(yōu)化器根據(jù)統(tǒng)計信息, 估算 SQL 要查找到結果集需要掃描讀取的數(shù)據(jù)行數(shù).這個值非常直觀顯示 SQL 的效率好壞, 原則上 rows 越少越好所踊。
  • extra:表示額外信息,如Using where,Start temporary,End temporary,Using temporary等概荷。

20. 為什么官方建議使用自增長主鍵作為索引秕岛?

結合B+Tree的特點,自增主鍵是連續(xù)的误证,在插入過程中盡量減少頁分裂继薛,即使要進行頁分裂,也只會分裂很少一部分愈捅。并且能減少數(shù)據(jù)的移動遏考,每次插入都是插入到最后±督鳎總之就是減少分裂和移動的頻率灌具。

插入連續(xù)的數(shù)據(jù):

圖片來自:https://www.javazhiyin.com/40232.html

[圖片上傳失敗...(image-b06b90-1653141194846)]

插入非連續(xù)的數(shù)據(jù):

[圖片上傳失敗...(image-689d34-1653141194846)]

21. 如何創(chuàng)建索引?

創(chuàng)建索引有三種方式譬巫。

1咖楣、 在執(zhí)行CREATE TABLE時創(chuàng)建索引

CREATE TABLE user_index2 (
id INT auto_increment PRIMARY KEY,
first_name VARCHAR (16),
last_name VARCHAR (16),
id_card VARCHAR (18),
information text,
KEY name (first_name, last_name),
FULLTEXT KEY (information),
UNIQUE KEY (id_card)
);

2、 使用ALTER TABLE命令去增加索引芦昔。

ALTER TABLE table_name ADD INDEX index_name (column_list);

ALTER TABLE用來創(chuàng)建普通索引诱贿、UNIQUE索引或PRIMARY KEY索引。

其中table_name是要增加索引的表名,column_list指出對哪些列進行索引珠十,多列時各列之間用逗號分隔料扰。

索引名index_name可自己命名,缺省時焙蹭,MySQL將根據(jù)第一個索引列賦一個名稱晒杈。另外,ALTER TABLE允許在單個語句中更改多個表壳嚎,因此可以在同時創(chuàng)建多個索引。3末早、 使用CREATE INDEX命令創(chuàng)建烟馅。

CREATE INDEX index_name ON table_name (column_list);

22. 創(chuàng)建索引時需要注意什么?

  • 非空字段:應該指定列為NOT NULL纸泄,除非你想存儲NULL构订。在mysql中纬凤,含有空值的列很難進行查詢優(yōu)化,因為它們使得索引寡润、索引的統(tǒng)計信息以及比較運算更加復雜。你應該用0舅柜、一個特殊的值或者一個空串代替空值梭纹;
  • 取值離散大的字段:(變量各個取值之間的差異程度)的列放到聯(lián)合索引的前面,可以通過count()函數(shù)查看字段的差異值致份,返回值越大說明字段的唯一值越多字段的離散程度高变抽;
  • 索引字段越小越好:數(shù)據(jù)庫的數(shù)據(jù)存儲以頁為單位一頁存儲的數(shù)據(jù)越多一次IO操作獲取的數(shù)據(jù)越大效率越高。

23. 建索引的原則有哪些氮块?

1绍载、最左前綴匹配原則,非常重要的原則滔蝉,mysql會一直向右匹配直到遇到范圍查詢(>击儡、<、between蝠引、like)就停止匹配阳谍,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的螃概,如果建立(a,b,d,c)的索引則都可以用到边坤,a,b,d的順序可以任意調整。

2谅年、=和in可以亂序茧痒,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優(yōu)化器會幫你優(yōu)化成索引可以識別的形式融蹂。

3旺订、盡量選擇區(qū)分度高的列作為索引弄企,區(qū)分度的公式是count(distinct col)/count(*),表示字段不重復的比例区拳,比例越大我們掃描的記錄數(shù)越少拘领,唯一鍵的區(qū)分度是1,而一些狀態(tài)樱调、性別字段可能在大數(shù)據(jù)面前區(qū)分度就是0约素,那可能有人會問,這個比例有什么經(jīng)驗值嗎笆凌?使用場景不同圣猎,這個值也很難確定,一般需要join的字段我們都要求是0.1以上乞而,即平均1條掃描10條記錄送悔。

4、索引列不能參與計算爪模,保持列“干凈”欠啤,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很簡單屋灌,b+樹中存的都是數(shù)據(jù)表中的字段值洁段,但進行檢索時,需要把所有元素都應用函數(shù)才能比較共郭,顯然成本太大眉撵。所以語句應該寫成create_time = unix_timestamp(’2014-05-29’)。

5落塑、盡量的擴展索引纽疟,不要新建索引。比如表中已經(jīng)有a的索引憾赁,現(xiàn)在要加(a,b)的索引污朽,那么只需要修改原來的索引即可。

24. 使用索引查詢一定能提高查詢的性能嗎龙考?

通常通過索引查詢數(shù)據(jù)比全表掃描要快蟆肆。但是我們也必須注意到它的代價。

索引需要空間來存儲晦款,也需要定期維護炎功, 每當有記錄在表中增減或索引列被修改時,索引本身也會被修改缓溅。 這意味著每條記錄的I* NSERT蛇损,DELETE,UPDATE將為此多付出4,5 次的磁盤I/O淤齐。 因為索引需要額外的存儲空間和處理股囊,那些不必要的索引反而會使查詢反應時間變慢。使用索引查詢不一定能提高查詢性能更啄,索引范圍查詢(INDEX RANGE SCAN)適用于兩種情況:

  • 基于一個范圍的檢索稚疹,一般查詢返回結果集小于表中記錄數(shù)的30%。
  • 基于非唯一性索引的檢索祭务。

25. 什么情況下不走索引(索引失效)内狗?

1、使用!= 或者 <> 導致索引失效

2义锥、類型不一致導致的索引失效

3柳沙、函數(shù)導致的索引失效

如:

SELECT * FROM user WHERE DATE(create_time) = '2020-09-03';

如果使用函數(shù)在索引列,這是不走索引的缨该。

4偎行、運算符導致的索引失效

SELECT * FROM user WHERE age - 1 = 20;

如果你對列進行了(+川背,-贰拿,*,/熄云,!), 那么都將不會走索引膨更。

5、OR引起的索引失效

SELECT * FROM user WHERE name = '張三' OR height = '175';

OR導致索引是在特定情況下的缴允,并不是所有的OR都是使索引失效荚守,如果OR連接的是同一個字段,那么索引不會失效练般,反之索引失效矗漾。

6、模糊搜索導致的索引失效

SELECT * FROM user WHERE name LIKE '%冰';

當%放在匹配字段前是不走索引的薄料,放在==后面==才會走索引敞贡。

7、NOT IN摄职、NOT EXISTS導致索引失效

26. 自適應哈希索引

InnoDB中不存在哈希索引, 但是哈希索引確實有利于快速查找, 于是InnoDB引入了"自適應哈希索引", 在某些索引值被使用的非常頻繁時, InnoDB會在內存中的B+樹結構之上創(chuàng)建一個哈希索引, 用于這些頻繁使用的索引值的快速查找, 使得其存有哈咸芤郏快速查找的特點.

27 .索引相關高頻面試題

  1. 索引是什么? 索引優(yōu)缺點?
    • 索引類似于目錄, 進行數(shù)據(jù)的快速定位
    • 優(yōu)點: 加快數(shù)據(jù)檢索速度
    • 缺點: 創(chuàng)建索引和維護索引需要消耗空間和時間
  1. MySQL索引類型
    • 按存儲結構劃分 : B+Tree索引, Hash索引, FULLINDEX全文索引, R-TREE索引
    • 按應用層次劃分: 普通索引, 唯一索引, 聯(lián)合索引, 聚簇索引, 非聚簇索引
  1. 索引底層實現(xiàn)? 為什么使用B+樹, 而不是B樹, BST, AVL, 紅黑樹等等?
  2. 什么是聚簇索引和非聚簇索引?
  3. 非聚簇索引一定會回表嗎?
    (不一定, 覆蓋索引不會回表)
  4. 什么是聯(lián)合索引?為什么需要注意聯(lián)合索引中的字段順序?
  5. 什么是最左前綴原則?
  6. 什么是前綴索引?
  7. 什么是索引下推?
  8. 如何查看MySQL語句是否使用到索引?
    EXPLAIN SQL語句
    possible_key: 可能用到的索引(可以查看是否有冗余索引)
    key: 真正使用到的索引
  9. 為什么建議使用自增主鍵作為索引?
    (索引維護可能造成頁分裂, 自增主鍵減少數(shù)據(jù)的移動和分裂)
  10. 建立索引的原則
    • 建立索引的字段最好為NOT NULL
    • 索引字段占用空間越小越好
    • 最左匹配原則
    • =和in建立索引時順序可以任意, 比如a = 1 and b = 2 and c = 3 建立(a, b, c)和(b, a, c)索引效果是一樣的, MySQL查詢優(yōu)化器會進行優(yōu)化
    • 建立的索引讓索引的選擇性盡可能接近1, 唯一索引的索引選擇性為1
    • 盡量擴展索引, 不要讓索引冗余, 如有SQL需要對單個a進行索引, 那么上述條件建立的索引應該為(a, b, c)或(a, c, b)
    • 索引列不能參與計算
  1. 什么情況下索引失效?
    • 使用 != 或 <>
    • 類型不一致導致索引失效
    • 函數(shù)導致的索引失效, 函數(shù)用在索引列時, 不走索引
      SELECT * FROM t WHERE DATE(create_time) = 'yyyy-MM-dd'
    • 運算符導致的索引失效
      SELECT * FROM t WHERE k - 1 = 2, 若有INDEX(k), 則不走索引
    • OR引起的索引失效
      SELECT * FROM t WHERE k = 1 OR j = 2, 若有INDEX(k), 則不走索引, 如果OR連接的時同一個字段, 則不會失效
    • 模糊查詢導致的索引失效
      SELECT * FROM t WHERE name = '%三', %放字符串字段前匹配不走索引
    • NOT IN, NOT EXISTS導致索引失效

【面向校招】全力備戰(zhàn)2023Golang實習與校招

歡迎群共同進步:
QQ群:1007576722

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市谷市,隨后出現(xiàn)的幾起案子蛔垢,更是在濱河造成了極大的恐慌,老刑警劉巖迫悠,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹏漆,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機甫男,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門且改,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人板驳,你說我怎么就攤上這事又跛。” “怎么了若治?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵慨蓝,是天一觀的道長。 經(jīng)常有香客問我端幼,道長礼烈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任婆跑,我火速辦了婚禮此熬,結果婚禮上,老公的妹妹穿的比我還像新娘滑进。我一直安慰自己犀忱,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布扶关。 她就那樣靜靜地躺著阴汇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪节槐。 梳的紋絲不亂的頭發(fā)上搀庶,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音铜异,去河邊找鬼哥倔。 笑死,一個胖子當著我的面吹牛揍庄,可吹牛的內容都是我干的咆蒿。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼币绩,長吁一口氣:“原來是場噩夢啊……” “哼蜡秽!你這毒婦竟也來了?” 一聲冷哼從身側響起缆镣,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤芽突,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后董瞻,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寞蚌,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡田巴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了挟秤。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壹哺。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖艘刚,靈堂內的尸體忽然破棺而出管宵,到底是詐尸還是另有隱情,我是刑警寧澤攀甚,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布箩朴,位于F島的核電站,受9級特大地震影響秋度,放射性物質發(fā)生泄漏炸庞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一荚斯、第九天 我趴在偏房一處隱蔽的房頂上張望埠居。 院中可真熱鬧,春花似錦事期、人聲如沸滥壕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捏浊。三九已至懂衩,卻和暖如春撞叨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背浊洞。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工牵敷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人法希。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓枷餐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親苫亦。 傳聞我的和親對象是個殘疾皇子毛肋,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容