国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【mysql進(jìn)階-彩蛋篇】深入理解順序io和隨機(jī)io(全網(wǎng)最詳細(xì)篇)

這篇具有很好參考價(jià)值的文章主要介紹了【mysql進(jìn)階-彩蛋篇】深入理解順序io和隨機(jī)io(全網(wǎng)最詳細(xì)篇)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

MySql系列整體欄目


內(nèi)容 鏈接地址
【一】深入理解mysql索引本質(zhì) https://blog.csdn.net/zhenghuishengq/article/details/121027025
【二】深入理解mysql索引優(yōu)化以及explain關(guān)鍵字 https://blog.csdn.net/zhenghuishengq/article/details/124552080
【三】深入理解mysql的索引分類,覆蓋索引(失效),回表,MRR https://blog.csdn.net/zhenghuishengq/article/details/128273593
【四】深入理解mysql事務(wù)本質(zhì) https://blog.csdn.net/zhenghuishengq/article/details/127753772
【五】深入理解mvcc機(jī)制 https://blog.csdn.net/zhenghuishengq/article/details/127889365
【六】深入理解mysql的內(nèi)核查詢成本計(jì)算 https://blog.csdn.net/zhenghuishengq/article/details/128820477
【七】深入理解mysql性能優(yōu)化以及解決慢查詢問(wèn)題 https://blog.csdn.net/zhenghuishengq/article/details/128854433
【八】深入理解innodb和buffer pool底層結(jié)構(gòu)和原理 https://blog.csdn.net/zhenghuishengq/article/details/128993871
【九】深入理解mysql執(zhí)行的底層機(jī)制 https://blog.csdn.net/zhenghuishengq/article/details/128100377
【十】深入理解mysql集群的高可用機(jī)制 https://blog.csdn.net/zhenghuishengq/article/details/126239652
【彩蛋篇】深入理解順序io和隨機(jī)io https://blog.csdn.net/zhenghuishengq/article/details/129080088

一,順序io和隨機(jī)io

1,機(jī)械硬盤的組成

在研究順序io和隨機(jī)io之前,先了解一下這個(gè)機(jī)械磁盤,一個(gè)機(jī)械磁盤的官方圖片如下,其主要由主軸,磁頭,磁盤,磁頭臂等等部分組成。接下來(lái)談一下各個(gè)組件的作用。
【mysql進(jìn)階-彩蛋篇】深入理解順序io和隨機(jī)io(全網(wǎng)最詳細(xì)篇)

磁盤 :數(shù)據(jù)是存儲(chǔ)在磁盤的盤片上面的,磁盤由多個(gè)盤片組成,主要是通過(guò)盤片的轉(zhuǎn)動(dòng)來(lái)讓磁頭讀取數(shù)據(jù)的。

磁頭:在需要讀取數(shù)據(jù)的時(shí)候,磁頭就會(huì)移到這個(gè)盤片上面讀取數(shù)據(jù),如果出現(xiàn)斷電的情況,那么磁頭就會(huì)從盤片上移開(kāi)移回到原來(lái)的位置,磁頭和盤片之間的距離非常的小。

磁頭臂:磁頭臂主要是控制這個(gè)磁頭進(jìn)行一個(gè)移到和旋轉(zhuǎn),讓磁頭去讀取內(nèi)容和歸位。由于多個(gè)磁頭都綁定在一個(gè)磁頭臂上面,因此多個(gè)磁頭都是一起移動(dòng)的,其距離,方向等都是一模一樣的。

主軸:通過(guò)主軸的轉(zhuǎn)動(dòng)來(lái)實(shí)現(xiàn)這個(gè)盤片的移動(dòng)。

2,磁盤

在磁盤內(nèi)部,又對(duì) 磁盤上的每個(gè)盤片 進(jìn)行了更加精確的細(xì)分。如下圖,每個(gè)盤片上面都由磁道和扇區(qū)組成,磁道是由一個(gè)一個(gè)的小圓環(huán)組成,每一個(gè)圓圈又進(jìn)行了一個(gè)更小的劃分,被稱為扇區(qū),如下面所示,一個(gè)磁道由八個(gè)扇區(qū)組成。

現(xiàn)在市面上流行的基本上是這種,一個(gè)磁盤八個(gè)扇區(qū),每個(gè)扇區(qū)存儲(chǔ)512個(gè)字節(jié)數(shù)據(jù),并且在磁盤中也是以頁(yè)為單位存儲(chǔ)數(shù)據(jù),和innodb的頁(yè)不同,他是八個(gè)扇區(qū)為一個(gè)頁(yè),即一頁(yè)大小為4kb,在讀取某一個(gè)扇區(qū)的內(nèi)容時(shí),會(huì)將一頁(yè)的數(shù)據(jù)全部給讀取出來(lái),因此一般一次磁盤io出來(lái)的數(shù)據(jù)就是4kb。如innodb存儲(chǔ)引擎,在存儲(chǔ)數(shù)據(jù)時(shí),innodb中的頁(yè)就是16kb的,因此存滿一頁(yè)數(shù)據(jù)需要四次的磁盤io。
【mysql進(jìn)階-彩蛋篇】深入理解順序io和隨機(jī)io(全網(wǎng)最詳細(xì)篇)

又由于一個(gè)磁盤上面存在多個(gè)盤片,而多個(gè)磁頭又是固定在磁盤臂上面的,那么多個(gè)盤片就會(huì)形成如下圖所示,形成一個(gè)圓柱體,多個(gè)盤片對(duì)應(yīng)位置的磁道就形成了一個(gè)柱面。如下面的黃色部分,四個(gè)盤面都有這個(gè)黃色的磁道,這樣黃色部分的四個(gè)磁道就形成了一個(gè)圓柱體狀的柱面。因此要確定數(shù)據(jù)在哪個(gè)位置,首先得確定柱面號(hào),即是屬于黃色部分還是藍(lán)色部分,先將這個(gè)圓柱體狀的柱面找到,再確定盤片號(hào),即數(shù)據(jù)是在哪個(gè)盤片的盤面上,最后確定扇區(qū)。

【mysql進(jìn)階-彩蛋篇】深入理解順序io和隨機(jī)io(全網(wǎng)最詳細(xì)篇)

在確定數(shù)據(jù)的位置之后,就需要開(kāi)始移動(dòng)這個(gè)磁頭,將磁頭定位到具體磁道,如上圖的最上面的那個(gè)磁頭,在0號(hào)盤面上,其先定位到黃色部分的那個(gè)磁道;在定位到具體的磁道之后,就通過(guò)這個(gè)主軸將盤片轉(zhuǎn)動(dòng),將扇區(qū)轉(zhuǎn)動(dòng)到磁頭指向的地方,這樣就可以定位到具體的扇區(qū)了,那么就可以將扇區(qū)的全部?jī)?nèi)容讀取出。

在整個(gè)讀取數(shù)據(jù)的過(guò)程中,主要分為三個(gè)時(shí)間:尋找磁道和盤面時(shí)間 + 盤面旋轉(zhuǎn)時(shí)間 + 讀取和傳輸數(shù)據(jù)的時(shí)間 ,就是一次磁盤的io讀取數(shù)據(jù)的時(shí)間,大概在 9 - 10ms 左右。尋找磁道和盤面需要移動(dòng)磁頭臂,而盤面旋轉(zhuǎn)找扇區(qū)的時(shí)間可以忽略不,因?yàn)楝F(xiàn)在的設(shè)備都是 5600r/s,7200r/s,轉(zhuǎn)一圈的需要的時(shí)間微乎其微;從磁盤讀取數(shù)據(jù)由于是按扇區(qū)直接讀取,其時(shí)間也可以忽略不計(jì);那么這個(gè)尋找磁道和盤面,就需要花費(fèi)最多的時(shí)間了,因?yàn)樾枰獊?lái)回移動(dòng)磁頭,這是一個(gè)很重的物理量操作。

因此這就解釋了為什么要按扇區(qū)讀取數(shù)據(jù)了,因?yàn)槎ㄎ坏骄唧w的位置花費(fèi)的時(shí)間長(zhǎng),所以直接讀取整個(gè)扇區(qū)的數(shù)據(jù),省的將磁頭移來(lái)移去,并且在這種讀取磁盤數(shù)據(jù)時(shí),會(huì)順便的將周圍的扇區(qū)里面的值也讀取出來(lái),也是為了解決移動(dòng)磁頭很耗時(shí)的問(wèn)題,這種方式被稱為預(yù)讀,如讀取mysql數(shù)據(jù),會(huì)通過(guò)預(yù)讀的方式將周圍的數(shù)據(jù)讀取出來(lái)。

因此,磁盤讀取數(shù)據(jù)的最小單位就是扇區(qū)。即使只需要讀取里面的一個(gè)字節(jié),也需要將整個(gè)扇區(qū)的內(nèi)容全部讀出。

3,順序io和隨機(jī)io

在得知磁盤的底層運(yùn)行原理之后,這里就知道了為啥隨機(jī)io要比順序io慢的原因了。由于在磁盤中讀取數(shù)據(jù)時(shí),盤面旋轉(zhuǎn)的時(shí)間和讀取數(shù)據(jù)的時(shí)間可以忽略不計(jì),主要是這個(gè)尋找磁道和盤面要花較多的時(shí)間,即移動(dòng)磁頭需要花費(fèi)大量的時(shí)間,那么主要是在這個(gè)地方拉開(kāi)時(shí)間差的。
【mysql進(jìn)階-彩蛋篇】深入理解順序io和隨機(jī)io(全網(wǎng)最詳細(xì)篇)

舉個(gè)例子,依舊選擇上面的黃色部分的磁道,那么拿順序io來(lái)說(shuō),由于順序io是有序的,那么如果數(shù)據(jù)只分布在一個(gè)磁道里面,那么這些數(shù)據(jù)都是連續(xù)有序的,那么讀取這一個(gè)磁道的數(shù)據(jù),順序io和隨機(jī)io可能都差不多,因?yàn)榇蓬^不需要移動(dòng),隨機(jī)io產(chǎn)生的時(shí)間可能比順序io產(chǎn)生的時(shí)間多就是磁道旋轉(zhuǎn)的次數(shù),可能隨機(jī)會(huì)多轉(zhuǎn)幾圈

但是,如果數(shù)據(jù)隨機(jī)分布在整個(gè)盤片上,那就不一樣了。依舊選擇黃色部分和最外面的藍(lán)色部分兩個(gè)磁道,假設(shè)數(shù)據(jù)隨機(jī)分布在兩個(gè)磁道上面,旋轉(zhuǎn)和讀取的時(shí)間忽略不計(jì),那么順序io只需要磁頭移動(dòng)兩次;而隨機(jī)io就不一樣了,上面八個(gè)扇區(qū),如果第一次在這個(gè)磁道,第二次又去了那個(gè)磁道…,那么隨機(jī)io的磁頭移動(dòng)的次數(shù)是2到16次,這樣順序io是小于或者遠(yuǎn)小于隨機(jī)io的時(shí)間的

照此類推,假設(shè)要讀取的數(shù)據(jù)分布在整個(gè)磁盤的隨機(jī)位置,如上圖假設(shè)10個(gè)磁道,那么順序io的磁頭只需要移動(dòng)10次,但是隨機(jī)io需要移動(dòng) 10 到 80次,這樣才能將數(shù)據(jù)全部讀完,由于移動(dòng)時(shí)間是整個(gè)時(shí)間最耗時(shí)的,因此隨機(jī)io在最壞的情況下,其消耗的時(shí)間遠(yuǎn)遠(yuǎn)大于順序io。而且上面只討論在一個(gè)盤面,如果是在多個(gè)盤面的情況下,其隨機(jī)IO的最壞時(shí)間更要遠(yuǎn)遠(yuǎn)的超出這個(gè)順序IO的時(shí)間了。

順序io的效率是隨機(jī)io的40-400倍,當(dāng)然除了順序讀,順序?qū)懸彩请S機(jī)寫的10-100倍,其原理一樣,主要是尋道時(shí)間比較長(zhǎng)。

4,預(yù)讀

磁盤在讀取數(shù)據(jù)時(shí),直接將一個(gè)扇區(qū)的數(shù)據(jù)讀取出,這個(gè)行為被稱為預(yù)讀。不僅僅是在磁盤中,在cpu,內(nèi)存,甚至在整個(gè)計(jì)算機(jī)中,預(yù)讀的使用都比較頻繁。和計(jì)算機(jī)中的局部性原理相關(guān),這個(gè)原理也是在磁盤,內(nèi)存,ssd盤中都會(huì)使用到這個(gè)原理。即一個(gè)數(shù)據(jù)在被讀取時(shí),其附近的的數(shù)據(jù)也通常會(huì)被使用。

在數(shù)據(jù)預(yù)讀的時(shí)候,可能并不只讀一個(gè)扇區(qū),而是讀連著的幾個(gè)扇區(qū),數(shù)據(jù)預(yù)讀的單位是以頁(yè)為單位的,一頁(yè)的大小大概在4kb左右,所以操作系統(tǒng)在處理磁盤的數(shù)據(jù)的時(shí)候,是以頁(yè)為單位將數(shù)據(jù)載入到內(nèi)存中的。

看一段代碼,如下

/**
 * @Author: zhenghuisheng
 * @Date: 2023/02/13 02:03
 */
public class ArrayTest {
    public static void main(String[] args) {
        int k = 10000 , p = 10000 , sum1 = 0 , sum2 = 0;
        //定義一個(gè)二維數(shù)組
        int data[][] = new int[k][p];
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < p; j++) {
                data[i][j] = i % 10;
            }
        }
        long firstTime = System.currentTimeMillis();
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < p; j++) {
                //按行操作
                sum1 += data[i][j];
            }
        }
        System.out.println("按行操作消耗的時(shí)間 :"+(System.currentTimeMillis() - firstTime));

        long secondTime = System.currentTimeMillis();
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < p; j++) {
                //按列操作
                sum2 += data[j][i];
            }
        }
        System.out.println("按列操作消耗的時(shí)間 :"+(System.currentTimeMillis()-secondTime));
    }
}

其運(yùn)行結(jié)果如下,其按列消耗的時(shí)間大概是按行消耗消耗的時(shí)間的30倍。而且這不是最壞的情況,因?yàn)殡S機(jī)io的時(shí)間是不確定的,但是肯定會(huì)大于順序io。

按行消耗的時(shí)間 : 118ms
按列消耗的時(shí)間 : 3022ms

一個(gè)二維數(shù)組,其實(shí)就是由多個(gè)一維數(shù)組組成。而在一維數(shù)組中,其內(nèi)存地址是一塊連續(xù)的空間,那么在按行讀取數(shù)據(jù)的情況下,這個(gè)二維數(shù)組也是一塊連續(xù)的地址。如下面這個(gè)數(shù)組

【mysql進(jìn)階-彩蛋篇】深入理解順序io和隨機(jī)io(全網(wǎng)最詳細(xì)篇)

其按行讀取數(shù)據(jù)的過(guò)程如下圖,其就是一個(gè)內(nèi)存的順序讀取數(shù)據(jù)的過(guò)程。其值從1009,一直到1020都是排好序的,因此在數(shù)組中按行讀就是一個(gè)順序讀取數(shù)據(jù)的一個(gè)過(guò)程。

【mysql進(jìn)階-彩蛋篇】深入理解順序io和隨機(jī)io(全網(wǎng)最詳細(xì)篇)

按列讀取數(shù)據(jù)就不一樣了,由于按行是順序的連續(xù)的地址,那么按列肯定就是不連續(xù)的,隨機(jī)的地址了,因此按列讀取數(shù)據(jù)就是一種類似于內(nèi)存的隨機(jī)讀取數(shù)據(jù)的過(guò)程。如下圖,在讀取到第一個(gè)數(shù)據(jù)后,讀取第二個(gè)數(shù)據(jù)就要開(kāi)始找位置了,我這里數(shù)據(jù)少,是在第5個(gè)位置,但是如果像上面的代碼是10000 x 10000的情況下,那么就需要找找到第10001個(gè)數(shù)據(jù),才是第二個(gè)數(shù)據(jù),第三個(gè)數(shù)據(jù)在20001個(gè)位置,以此類推…。這樣每個(gè)數(shù)據(jù)都需要跳來(lái)跳去的在這個(gè)連續(xù)的空間中尋找,這樣查詢時(shí)間就占很大一部分了。

【mysql進(jìn)階-彩蛋篇】深入理解順序io和隨機(jī)io(全網(wǎng)最詳細(xì)篇)

這就解釋了,為什么在計(jì)算機(jī)底層中,那么傾向于往順序io的方向優(yōu)化了。

5,innodb存儲(chǔ)引擎的順序io

首先磁盤通過(guò)預(yù)讀的方式讀取數(shù)據(jù),有可能不僅僅是加載磁盤中一頁(yè)數(shù)據(jù),也可能是加載好幾頁(yè)的數(shù)據(jù)(磁盤中一頁(yè)數(shù)據(jù)為8個(gè)扇區(qū)的數(shù)據(jù),每個(gè)扇區(qū)512kb,那么一頁(yè)就是4kb的數(shù)據(jù))。所以在innodb的存儲(chǔ)引擎中,也可能直接通過(guò)預(yù)讀的方式,將innodb的一頁(yè)甚至多頁(yè)數(shù)據(jù)給直接的全部讀取出來(lái),innodb一頁(yè)數(shù)據(jù)是16kb,和這個(gè)磁盤中的數(shù)據(jù)頁(yè)本質(zhì)不同。

并且在innodb的存儲(chǔ)引擎中,其索引的本質(zhì)就是一棵b+樹(shù),所有的數(shù)據(jù)都是在聚簇索引上面的,因此其內(nèi)部是排好序的,如果是順序io,那么一次就可以將當(dāng)前頁(yè)的數(shù)據(jù)和周圍頁(yè)的數(shù)據(jù)通過(guò)預(yù)讀的方式給讀取出來(lái),因此B+樹(shù)的有序性,也非常適應(yīng)這個(gè)順序讀寫,假設(shè)b+樹(shù)不是順序的,那么要讀取相鄰的順序,那么就可能需要不斷的來(lái)回移動(dòng)這個(gè)磁頭來(lái)定位,這樣也是需要花費(fèi)大量的時(shí)間的,所以mysql底層也是選擇有序的b+樹(shù)來(lái)作為索引,也是更符合順序讀寫的原則。所以b+樹(shù)的葉子結(jié)點(diǎn)為什么是順序的,也可以從這個(gè)順序io這個(gè)方面來(lái)解釋

因此在mysql內(nèi)部進(jìn)行優(yōu)化的時(shí)候,都是讓數(shù)據(jù)進(jìn)行順序讀寫的,而不是隨機(jī)讀寫的,如mysql對(duì)順序讀寫有這些體現(xiàn)點(diǎn):如MRR機(jī)制,對(duì)回表的id進(jìn)行一個(gè)排序,然后進(jìn)行一個(gè)順序的查找,從而減少回表時(shí)的隨機(jī)讀寫;還有redolog的日志,也是順序的寫,等等。其目的就是為了減少尋找磁道和扇區(qū)的時(shí)間,減少磁頭移動(dòng)的時(shí)間,因?yàn)榇蓬^移動(dòng)是一個(gè)機(jī)械運(yùn)動(dòng),是一個(gè)重操作,需要花費(fèi)大量的時(shí)間。

除了這個(gè)mysql內(nèi)部對(duì)順序讀寫有著一些相關(guān)的優(yōu)化,還有如kafka等內(nèi)部也是使用了這個(gè)順序io的。

這里主要是了解磁盤中的隨機(jī)讀和順序讀,當(dāng)然內(nèi)存,ssd盤等都有順序io和隨機(jī)io,雖然內(nèi)部實(shí)現(xiàn)方式和磁盤不大一樣,但是順序io的時(shí)間都是小于或者遠(yuǎn)小于隨機(jī)io的時(shí)間的。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-445940.html

到了這里,關(guān)于【mysql進(jìn)階-彩蛋篇】深入理解順序io和隨機(jī)io(全網(wǎng)最詳細(xì)篇)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包