最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于面試中常問(wèn)的數(shù)據(jù)庫(kù)回表問(wèn)題

 更新時(shí)間:2023年07月14日 09:36:27   作者:Wis57  
這篇文章主要介紹了關(guān)于面試中常問(wèn)的數(shù)據(jù)庫(kù)回表問(wèn)題,回表就是先通過(guò)數(shù)據(jù)庫(kù)索引掃描出數(shù)據(jù)所在的行,再通過(guò)行主鍵id取出索引中未提供的數(shù)據(jù),即基于非主鍵索引的查詢(xún)需要多掃描一棵索引樹(shù),需要的朋友可以參考下

什么是回表?為什么需要回表?

小伙伴們?cè)诿嬖嚨臅r(shí)候,有一個(gè)特別常見(jiàn)的問(wèn)題,那就是數(shù)據(jù)庫(kù)的回表。

索引結(jié)構(gòu)

要搞明白這個(gè)問(wèn)題,需要大家首先明白 MySQL 中索引存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)。這個(gè)其實(shí)很多小伙伴可能也都聽(tīng)說(shuō)過(guò),B+Tree 嘛!

B+Tree 是什么?那你得先明白什么是 B-Tree,來(lái)看如下一張圖:

在這里插入圖片描述

前面是 B-Tree,后面是 B+Tree,兩者的區(qū)別在于:

  • B-Tree 中,所有節(jié)點(diǎn)都會(huì)帶有指向具體記錄的指針;
  • B+Tree 中只有葉子結(jié)點(diǎn)會(huì)帶有指向具體記錄的指針。
  • B-Tree 中不同的葉子之間沒(méi)有連在一起;
  • B+Tree 中所有的葉子結(jié)點(diǎn)通過(guò)指針連接在一起。
  • B-Tree 中可能在非葉子結(jié)點(diǎn)就拿到了指向具體記錄的指針,搜索效率不穩(wěn)定;
  • B+Tree 中,一定要到葉子結(jié)點(diǎn)中才可以獲取到具體記錄的指針,搜索效率穩(wěn)定。

基于上面兩點(diǎn)分析,我們可以得出如下結(jié)論:

B+Tree 中,由于非葉子結(jié)點(diǎn)不帶有指向具體記錄的指針,所以非葉子結(jié)點(diǎn)中可以存儲(chǔ)更多的索引項(xiàng),這樣就可以有效降低樹(shù)的高度,進(jìn)而提高搜索的效率。

B+Tree 中,葉子結(jié)點(diǎn)通過(guò)指針連接在一起,這樣如果有范圍掃描的需求,那么實(shí)現(xiàn)起來(lái)將非常容易,而對(duì)于 B-Tree,范圍掃描則需要不停的在葉子結(jié)點(diǎn)和非葉子結(jié)點(diǎn)之間移動(dòng)。

對(duì)于第一點(diǎn),一個(gè) B+Tree 可以存多少條數(shù)據(jù)呢?以主鍵索引的 B+Tree 為例(二級(jí)索引存儲(chǔ)數(shù)據(jù)量的計(jì)算原理類(lèi)似,但是葉子節(jié)點(diǎn)和非葉子節(jié)點(diǎn)上存儲(chǔ)的數(shù)據(jù)格式略有差異),我們可以簡(jiǎn)單算一下。

計(jì)算機(jī)在存儲(chǔ)數(shù)據(jù)的時(shí)候,最小存儲(chǔ)單元是扇區(qū),一個(gè)扇區(qū)的大小是 512 字節(jié),而文件系統(tǒng)(例如 XFS/EXT4)最小單元是塊,一個(gè)塊的大小是 4KB。

InnoDB 引擎存儲(chǔ)數(shù)據(jù)的時(shí)候,是以頁(yè)為單位的,每個(gè)數(shù)據(jù)頁(yè)的大小默認(rèn)是 16KB,即四個(gè)塊。

基于這樣的知識(shí)儲(chǔ)備,我們可以大致算一下一個(gè) B+Tree 能存多少數(shù)據(jù)。

假設(shè)數(shù)據(jù)庫(kù)中一條記錄是 1KB,那么一個(gè)頁(yè)就可以存 16 條數(shù)據(jù)(葉子結(jié)點(diǎn));對(duì)于非葉子結(jié)點(diǎn)存儲(chǔ)的則是主鍵值+指針,在 InnoDB 中,一個(gè)指針的大小是 6 個(gè)字節(jié),假設(shè)我們的主鍵是 bigint ,那么主鍵占 8 個(gè)字節(jié),當(dāng)然還有其他一些頭信息也會(huì)占用字節(jié)我們這里就不考慮了,我們大概算一下,小伙伴們心里有數(shù)即可:

16*1024/(8+6)=1170

即一個(gè)非葉子結(jié)點(diǎn)可以指向 1170 個(gè)頁(yè),那么一個(gè)三層的 B+Tree 可以存儲(chǔ)的數(shù)據(jù)量為:

1170117016=21902400

可以存儲(chǔ) 2100萬(wàn) 條數(shù)據(jù)。

在 InnoDB 存儲(chǔ)引擎中,B+Tree 的高度一般為 2-4 層,這就可以滿(mǎn)足千萬(wàn)級(jí)的數(shù)據(jù)的存儲(chǔ),查找數(shù)據(jù)的時(shí)候,一次頁(yè)的查找代表一次 IO,那我們通過(guò)主鍵索引查詢(xún)的時(shí)候,其實(shí)最多只需要 2-4 次 IO 操作就可以了。

大家先搞明白這個(gè) B+Tree。

兩類(lèi)索引

大家知道,MySQL 中的索引有很多中不同的分類(lèi)方式,可以按照數(shù)據(jù)結(jié)構(gòu)分,可以按照邏輯角度分,也可以按照物理存儲(chǔ)分,其中,按照物理存儲(chǔ)方式,可以分為聚簇索引和非聚簇索引。

我們?nèi)粘Kf(shuō)的主鍵索引,其實(shí)就是聚簇索引(Clustered Index);主鍵索引之外,其他的都稱(chēng)之為非主鍵索引,非主鍵索引也被稱(chēng)為二級(jí)索引(Secondary Index),或者叫作輔助索引。

對(duì)于主鍵索引和非主鍵索引,使用的數(shù)據(jù)結(jié)構(gòu)都是 B+Tree,唯一的區(qū)別在于葉子結(jié)點(diǎn)中存儲(chǔ)的內(nèi)容不同:

主鍵索引的葉子結(jié)點(diǎn)存儲(chǔ)的是一行完整的數(shù)據(jù)。

非主鍵索引的葉子結(jié)點(diǎn)存儲(chǔ)的則是主鍵值。

這就是兩者最大的區(qū)別。

所以,當(dāng)我們需要查詢(xún)的時(shí)候:

如果是通過(guò)主鍵索引來(lái)查詢(xún)數(shù)據(jù),例如 select * from user where id=100,那么此時(shí)只需要搜索主鍵索引的 B+Tree 就可以找到數(shù)據(jù)。

如果是通過(guò)非主鍵索引來(lái)查詢(xún)數(shù)據(jù),例如 select * from user where username=‘javaboy’,那么此時(shí)需要先搜索 username 這一列索引的 B+Tree,搜索完成后得到主鍵的值,然后再去搜索主鍵索引的 B+Tree,就可以獲取到一行完整的數(shù)據(jù)。

對(duì)于第二種查詢(xún)方式而言,一共搜索了兩棵 B+Tree,第一次搜索 B+Tree 拿到主鍵值后再去搜索主鍵索引的 B+Tree,這個(gè)過(guò)程就是所謂的回表。

從上面的分析中我們也能看出,通過(guò)非主鍵索引查詢(xún)要掃描兩棵 B+Tree,而通過(guò)主鍵索引查詢(xún)只需要掃描一棵 B+Tree,所以如果條件允許,還是建議在查詢(xún)中優(yōu)先選擇通過(guò)主鍵索引進(jìn)行搜索。

一定會(huì)回表嗎?那么不用主鍵索引就一定需要回表嗎?

不一定!

如果查詢(xún)的列本身就存在于索引中,那么即使使用二級(jí)索引,一樣也是不需要回表的。

舉個(gè)例子,我有如下一張表:

在這里插入圖片描述

uname 和 address 字段組成了一個(gè)復(fù)合索引,那么此時(shí),雖然這是一個(gè)二級(jí)索引,但是索引樹(shù)的葉子節(jié)點(diǎn)中除了保存主鍵值,也保存了 address 的值。

我們來(lái)看如下分析:

在這里插入圖片描述

可以看到,此時(shí)使用到了 uname 索引,但是最后的 Extra 的值為 Using index,這就表示用到了索引覆蓋掃描(覆蓋索引),此時(shí)直接從索引中過(guò)濾不需要的記錄并返回命中的結(jié)果,這一步是在 MySQL 服務(wù)器層完成的,并且不需要回表。

擴(kuò)展

基于第一、二小節(jié)的分析,我們?cè)賮?lái)捋一捋為什么在數(shù)據(jù)庫(kù)中建議使用自增主鍵。

自增主鍵往往占用空間比較小,int 占 4 個(gè)字節(jié),bigint 占 8 個(gè)字節(jié)。由于二級(jí)索引的葉子節(jié)點(diǎn)存儲(chǔ)的就是主鍵,所以如果主鍵占用空間小,意味著二級(jí)索引的葉子節(jié)點(diǎn)將來(lái)占用的空間小(間接降低 B+Tree 的高度,提高搜索效率)。

自增主鍵插入的時(shí)候比較快,直接插入即可,不會(huì)涉及到葉子節(jié)點(diǎn)分裂等問(wèn)題(不需要挪動(dòng)其他記錄);而其他非自增主鍵插入的時(shí)候,可能要插入到兩個(gè)已有的數(shù)據(jù)中間,就有可能導(dǎo)致葉子節(jié)點(diǎn)分裂等問(wèn)題,插入效率低(要挪動(dòng)其他記錄)。

當(dāng)然,這個(gè)是基于技術(shù)層面的討論,如果業(yè)務(wù)上無(wú)法使用自增主鍵或者有其他要求導(dǎo)致無(wú)法使用自增主鍵,那沒(méi)辦法,在滿(mǎn)足新要求的情況下重新選擇一個(gè)最佳實(shí)踐吧。

到此這篇關(guān)于關(guān)于面試中常問(wèn)的數(shù)據(jù)庫(kù)回表問(wèn)題的文章就介紹到這了,更多相關(guān)數(shù)據(jù)庫(kù)回表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Navicat Premium 15 無(wú)限試用腳本的方法

    詳解Navicat Premium 15 無(wú)限試用腳本的方法

    這篇文章主要介紹了Navicat Premium 15 無(wú)限試用腳本的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-11-11
  • SQL查詢(xún)的優(yōu)化技巧詳解

    SQL查詢(xún)的優(yōu)化技巧詳解

    這篇文章主要介紹了SQL查詢(xún)的優(yōu)化技巧詳解,查詢(xún)優(yōu)化的本質(zhì)是讓數(shù)據(jù)庫(kù)優(yōu)化器為SQL語(yǔ)句選擇最佳的執(zhí)行計(jì)劃。一般來(lái)說(shuō),對(duì)于在線交易處理(OLTP)系統(tǒng)的數(shù)據(jù)庫(kù),減少數(shù)據(jù)庫(kù)磁盤(pán)I/O是SQL語(yǔ)句性能優(yōu)化的首要方法,需要的朋友可以參考下
    2023-07-07
  • 達(dá)夢(mèng)數(shù)據(jù)庫(kù)如何設(shè)置自增主鍵的方法及注意事項(xiàng)

    達(dá)夢(mèng)數(shù)據(jù)庫(kù)如何設(shè)置自增主鍵的方法及注意事項(xiàng)

    這篇文章主要介紹了達(dá)夢(mèng)數(shù)據(jù)庫(kù)如何設(shè)置自增主鍵的方法及注意事項(xiàng)的相關(guān)資料,在達(dá)夢(mèng)數(shù)據(jù)庫(kù)中實(shí)現(xiàn)自增字段通常需要使用序列(sequence)和觸發(fā)器(trigger),需要的朋友可以參考下
    2024-09-09
  • 數(shù)據(jù)庫(kù)DDL操作卡死問(wèn)題原因、解決與預(yù)防指南

    數(shù)據(jù)庫(kù)DDL操作卡死問(wèn)題原因、解決與預(yù)防指南

    在數(shù)據(jù)庫(kù)管理過(guò)程中,執(zhí)行 ALTER TABLE 添加字段(DDL 操作)時(shí),可能會(huì)遇到操作卡死的情況,這不僅影響業(yè)務(wù)正常運(yùn)行,還可能導(dǎo)致鎖表、連接池耗盡等問(wèn)題,本文將深入分析 DDL 操作卡死的原因解決與預(yù)防,需要的朋友可以參考下
    2025-07-07
  • Redis和Memcache的區(qū)別總結(jié)

    Redis和Memcache的區(qū)別總結(jié)

    這篇文章主要介紹了Redis和Memcache的區(qū)別,用三個(gè)總結(jié)來(lái)說(shuō)明Redis和Memcache的區(qū)別,需要的朋友可以參考下
    2014-05-05
  • 讓你的insert操作速度增加1000倍的方法

    讓你的insert操作速度增加1000倍的方法

    大家平時(shí)都會(huì)使用insert語(yǔ)句,特別是有時(shí)候需要一個(gè)大批量的數(shù)據(jù)來(lái)做測(cè)試,一條一條insert將會(huì)是非常慢的,那么我們?nèi)绾巫屛覀兊膇nser更快呢。
    2009-08-08
  • Hive如何寫(xiě)exist/in子句示例詳解

    Hive如何寫(xiě)exist/in子句示例詳解

    這篇文章主要介紹了在Hive中使用EXISTS和IN子句進(jìn)行數(shù)據(jù)查詢(xún)的方法,EXISTS子句用于檢查子查詢(xún)是否至少返回一行記錄,而IN子句用于檢查某個(gè)值是否存在于指定的列表中,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-02-02
  • DBeaver下載安裝詳細(xì)教程

    DBeaver下載安裝詳細(xì)教程

    DBeaver是數(shù)據(jù)庫(kù)管理工具,如何下載安裝,下面將詳細(xì)介紹DBeaver下載安裝詳細(xì)教程,感興趣的朋友跟隨小編一起學(xué)習(xí)下吧
    2021-11-11
  • MSSQL轉(zhuǎn)MySQL數(shù)據(jù)庫(kù)的實(shí)際操作記錄

    MSSQL轉(zhuǎn)MySQL數(shù)據(jù)庫(kù)的實(shí)際操作記錄

    今天把一個(gè)MSSQL的數(shù)據(jù)庫(kù)轉(zhuǎn)成MySQL,在沒(méi)有轉(zhuǎn)換工具的情況下,對(duì)于字段不多的數(shù)據(jù)表我用了如下手功轉(zhuǎn)換的方法,還算方便。MSSQL使用企業(yè)管理器操作,MySQL用phpmyadmin操作。
    2010-06-06
  • 時(shí)序數(shù)據(jù)庫(kù)VictoriaMetrics源碼解析之寫(xiě)入與索引

    時(shí)序數(shù)據(jù)庫(kù)VictoriaMetrics源碼解析之寫(xiě)入與索引

    這篇文章主要為大家介紹了VictoriaMetrics時(shí)序數(shù)據(jù)庫(kù)的寫(xiě)入與索引源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05

最新評(píng)論

肥东县| 桃园市| 金沙县| 汪清县| 区。| 额济纳旗| 甘洛县| 海伦市| 松原市| 城固县| 临沭县| 平定县| 同仁县| 合水县| 民丰县| 绵竹市| 左云县| 菏泽市| 西乌珠穆沁旗| 驻马店市| 临安市| 理塘县| 宜兰市| 兴宁市| 沈阳市| 安庆市| 临朐县| 铜陵市| 建湖县| 涡阳县| 延寿县| 常州市| 上饶市| 乌兰浩特市| 图木舒克市| 韶关市| 赞皇县| 雷波县| 嘉定区| 西昌市| 北海市|