自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

扒一扒InnoDB數(shù)據(jù)在硬盤上是如何存放的

存儲 存儲軟件
在InnoDB中,每張表都有各自的主鍵(Primary Key),如果在創(chuàng)建表的時(shí)候顯式的定義主鍵,則InnoDB存儲引擎會按如下方式選擇或創(chuàng)建主鍵。

[[313009]]

本文轉(zhuǎn)載自微信公眾號「學(xué)習(xí)Java的小姐姐」,轉(zhuǎn)載本文請聯(lián)系學(xué)習(xí)Java的小姐姐公眾號。

索引組織表

在InnoDB存儲引擎中,表都是按照主鍵順序組織存放的,這種存儲方式的表被稱為索引組織表。

在InnoDB中,每張表都有各自的主鍵(Primary Key),如果在創(chuàng)建表的時(shí)候顯式的定義主鍵,則InnoDB存儲引擎會按如下方式選擇或創(chuàng)建主鍵。

首先判斷表中是否有非空的索引,如果有則第一個(gè)定義的非空索引作為主鍵

如果不符合上述條件,InnoDB存儲引擎自動創(chuàng)建一個(gè)6個(gè)字節(jié)大小的指針

這樣的描述太干癟啦,我們來動手操作下。

1.選擇第一個(gè)定義的非空索引

首先,我們創(chuàng)建表student,并填充兩條測試數(shù)據(jù),語句如下:

  1. create table student( 
  2. int , 
  3. int not null
  4. int not null
  5. UNIQUE key (a), 
  6. UNIQUE key (c), 
  7. UNIQUE key (b) 
  8. ); 
  9. insert into student select 1,2,3; 
  10. insert into student select 4,5,6; 

運(yùn)行結(jié)果如下,我們可以看出_rowid的值等于列c的值,那就說明當(dāng)前存儲的結(jié)構(gòu)是將c作為主鍵的。另外a是可以為空的,雖然他定義唯一鍵的是第一個(gè),但仍然不會作為主鍵。b雖然是先定義列,但是定義唯一鍵是在c之后,所以也不會被作為唯一鍵。

 

2.自動創(chuàng)建6個(gè)字節(jié)大小的指針

首先,我們創(chuàng)建表score,并填充兩條測試數(shù)據(jù),語句如下:

  1. create table score( 
  2. int , 
  3. int , 
  4. int
  5. UNIQUE key (a), 
  6. UNIQUE key (c), 
  7. UNIQUE key (b) 
  8. ); 
  9. insert into score select 1,2,3; 
  10. insert into score select 4,5,6; 

運(yùn)行結(jié)果如下,直接報(bào)錯(cuò)了,不認(rèn)為_rowid是他的列名,因?yàn)闆]有滿足條件的列能成為他的主鍵,所以其就自動創(chuàng)建指針來解決問題啦。

InnoDB的邏輯存儲結(jié)構(gòu)(整體)

表空間

表空間可以看做是InnoDB存儲引擎邏輯結(jié)構(gòu)的最高層,所以的數(shù)據(jù)都存放在表空間里面。

在默認(rèn)情況下,InnoDB存儲引擎有一個(gè)共享表空間ibdata1,即所有數(shù)據(jù)都存放在這個(gè)表空間里面。當(dāng)然也可以在my.ini參數(shù)文件中啟用innodb_file_per_table,則每張表的數(shù)據(jù)就可以單獨(dú)放在一個(gè)表空間中。

注意:即使啟用innodb_file_per_table參數(shù),一些回滾信息,系統(tǒng)事務(wù)信息等還是在共享的表空間中,其隨著時(shí)間的變化大小還是會不斷增大的。單獨(dú)的表空間只會存放一些數(shù)據(jù)及索引信息。

在InnoDB存儲引擎中,對段的管理都是由引擎自身所完成的,DBA不能也沒必要對其進(jìn)行控制。

區(qū)

區(qū)是由連續(xù)頁組成的空間,在任何情況下每個(gè)區(qū)的大小都是1MB,頁的大小為16kb,所以一個(gè)區(qū)一共有64個(gè)連續(xù)的頁。

下面詳細(xì)描述。

下面詳細(xì)描述。

InnoDB行記錄格式(重點(diǎn))

InnoDB存儲引擎和大多數(shù)數(shù)據(jù)庫一樣,記錄是以行的形式純純的,這就是意味著頁中保存著表的一行行數(shù)據(jù)。那么問題就來了,他這一行數(shù)據(jù)是包括哪些部分,除了具體的數(shù)據(jù),還有其他的一些額外信息嗎?

首先,我們先來看一下如果沒有指定行格式,其默認(rèn)的行格式是什么?

新建表test,擁有的字段a,b ,c 。

  1. create table test( 
  2. varchar(10), 
  3. varchar (10) not null
  4. char(10) 
  5. ); 
  6. insert into test values'001','Andy','compter'); 
  7. insert into test values'002','Bob',NULL); 

如下圖所示,默認(rèn)的行格式是Compact ,該行格式是在MySQL5.0中引入的,其設(shè)計(jì)目標(biāo)是高校的存儲數(shù)據(jù)。簡單來說,一個(gè)頁存放的行數(shù)據(jù)越多,其性能越高。針對這個(gè)描述,咱先放在一邊,之后看到其他的行格式,咱對比著看,為啥compact性能高?

 


 

 

下圖為行格式Compact的大概結(jié)構(gòu),先瞅一眼,主要分為兩個(gè)部分,額外信息和真實(shí)數(shù)據(jù)。額外信息包括變成字段長度,NULL值列表,記錄頭信息,真實(shí)數(shù)據(jù)即為該行記錄有多少列,每列數(shù)據(jù)有哪些。其中記錄頭信息包括記錄刪除位,記錄類型,下一個(gè)指針的位置。

注意,記錄頭信息還有很多為其他信息,但是重要的就這幾個(gè)。是不是不知道他們是干撒的,一臉懵逼中,沒事,這還是混個(gè)臉熟,下一部分來慢慢盤他。

 

變長字段長度

MySQL支持一些變長的數(shù)據(jù)類型,如varchar,text,blob,變長長度存儲多少字節(jié)的數(shù)據(jù)是不固定的,所以我們在存儲真實(shí)數(shù)據(jù)的時(shí)候,需要將這些數(shù)據(jù)占用的字節(jié)數(shù)也要存儲起來。

剛才我們新增了兩條數(shù)據(jù),先拿第一個(gè)數(shù)據(jù)為例,將真正數(shù)據(jù)占用的字節(jié)長度都存放在記錄的開頭部位,從而形成一個(gè)變長字段長度列表,逆序存放。如下圖,所以最終第一條記錄存放的十六進(jìn)制為08 04 03,他們之間沒有空格,是為了顯示的效果才加了空格。那第二條記錄很明顯是03 03.

注意:如果表中沒有變長字段,則該字段不存在。

 

NULL值列表

我們知道表中的某些列可能存儲NULL值,如果這些NULL值放在記錄的真實(shí)數(shù)據(jù)中存儲會占用空間,所以Compact將這些值為NULL的列統(tǒng)一管理起來,存儲在NULL表中。

注意:跟變長字段一樣,如果表中沒有NULL值的列,則該字段不存在。注意:MySQL規(guī)定NULL值列表必須是整數(shù)個(gè)字節(jié)的位表示,如果使用的二進(jìn)制位歌手不是整數(shù)個(gè)字節(jié),則在字節(jié)的高位補(bǔ)0.

第一行數(shù)據(jù)雖然沒有NULL值,但是a,c是可能存儲NULL值的列,所以NULL值列表如下,0表示列所對應(yīng)的值不為NULL,1表示列所對應(yīng)的值為NULL。

 

第二行數(shù)據(jù)a不是NULL,c是NULL,所以對應(yīng)的NULL值列表如下。

 

記錄頭信息

  • 記錄刪除位(delete_mask):0為未刪除,1為刪除
  • 記錄類型(record_type):0表示普通記錄,1表示B+樹非葉子節(jié)點(diǎn)記錄,2表示最小記錄,3表示最大記錄。
  • 下一個(gè)指針的位置(next_record):表示從當(dāng)前記錄的真實(shí)數(shù)據(jù)到下一條記錄的真實(shí)數(shù)據(jù)之間的地址偏移量。比如第一條記錄的next_record為20,那么意味從第一條記錄的真實(shí)數(shù)據(jù)的地址處向后找32個(gè)字節(jié)便是下一條記錄的真實(shí)數(shù)據(jù)。實(shí)際上就是鏈表結(jié)構(gòu)。

InnoDB數(shù)據(jù)頁結(jié)構(gòu)(重點(diǎn))

下圖為數(shù)據(jù)頁的整體結(jié)構(gòu),咱先來了解下大概,再慢慢盤它。

 

文件頭(File Header)

頁的一些通用信息,包括該頁屬于哪個(gè)表空間,InnoDB存儲引擎頁的類型。

頁頭(Page Header)

記錄數(shù)據(jù)頁的狀態(tài)信息。

最小記錄+最大記錄(Infimum+supermum)

在InnoDB存儲引擎中,每個(gè)數(shù)據(jù)頁都有兩條虛擬的行記錄,用來限定記錄的邊界。

Infimum記錄是指比該頁中任何主鍵值都要小的值,Supermum記錄是指比該頁中任何主鍵值都要大的值。

這兩個(gè)值在頁創(chuàng)建時(shí)都會被的創(chuàng)建,并且在任何情況下不會被刪除。

這兩條記錄的構(gòu)造十分簡單,都是有5個(gè)字節(jié)大小的記錄頭信息和8個(gè)字節(jié)的固定部分組成的。

注意:上面提到了最小記錄的record_type為2,最大記錄的record_type為3。

用戶記錄(User Records)

重點(diǎn)來了,這邊是數(shù)據(jù)實(shí)際存儲位置,上面已經(jīng)針對行格式做了詳細(xì)的劃分,現(xiàn)在咱就長話短說啦。

如果我刪除了第二行記錄,這條記錄并不是立刻刪除了,只是將刪除記錄位改為1啦。并且將他前面一條數(shù)據(jù)的指針指向他后面一條數(shù)據(jù)的地址,從而跳過這一條數(shù)據(jù)。

至于為什么會這樣做呢?是為了節(jié)約時(shí)間和空間的消耗。如果在刪除的時(shí)候,立刻從磁盤上移除,那么其他記錄在磁盤上重新排列需要性能消耗,所以在刪除的時(shí)候,只會將所有被刪除的記錄組成一個(gè)垃圾鏈表,稍后操作?;蛘哂行录o(jì)錄插入的時(shí)候,覆蓋掉剛才的存儲空間。

 

空閑空間(Free Space)

不重要。

頁面目錄(Page Directory)

我們現(xiàn)在已經(jīng)找到記錄在頁面中按照主鍵由小到達(dá)順序組成一個(gè)單鏈表,那如果想根據(jù)主鍵查詢頁中的某條記錄怎么辦?

最蠢的方法肯定是按單鏈表的順序從頭到尾的查找,因?yàn)橹挥兄狼懊嬉粭l記錄的記錄的地址,才能根據(jù)指針找到下一條記錄。但是這個(gè)有個(gè)明顯的缺點(diǎn),就是太慢了,如果有1000條數(shù)據(jù),一個(gè)個(gè)的查詢,如果最后一條記錄才滿足條件,那就太浪費(fèi)時(shí)間啦。

我們可以先從順序表中想想,如果順序表中要找一個(gè)記錄,我們除了從頭開始查之外,還可以采用二分法,可以提升查詢速度。

那么在單鏈表中是否可以采用二分法呢?答案是肯定的。即采用目錄的形式,將所有的記錄劃分為多個(gè)記錄塊,然后取每個(gè)記錄塊的最大的值,將其組成一個(gè)目錄,在查找的時(shí)候,先查目錄,能判斷在哪個(gè)區(qū)間內(nèi)。這個(gè)過程就類似于在書中找到某一個(gè)概念,要從目錄先找一樣。

文章尾部(File Tailer)

不重要。哈哈哈。

寫在最后

寫在最后

該篇借鑒的博文,書籍如下。

《MySQL技術(shù)內(nèi)幕——InnoDB存儲引擎》MySQL是如何運(yùn)行的https://blog.csdn.net/u010922732/article/details/82994253#%E4%B8%80%20%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E%E4%BD%9C%E7%94%A8%E4%BA%8E%E4%BB%80%E4%B9%88%E5%AF%B9%E8%B1%A1

https://juejin.im/post/5cb3e3dfe51d456e3428c0db

責(zé)任編輯:武曉燕 來源: 學(xué)習(xí)Java的小姐姐
相關(guān)推薦

2015-09-16 14:04:06

大數(shù)據(jù)巨頭

2015-09-21 10:07:31

2022-07-11 20:46:39

AQSJava

2019-10-21 10:59:52

編程語言JavaC

2019-09-10 07:29:44

2018-04-03 15:42:40

2023-01-30 22:10:12

BeanSpring容器

2015-09-16 14:11:47

2019-02-25 22:46:39

2023-04-10 23:05:54

NacosOpenFeignRibbon

2015-10-15 13:38:39

2015-08-18 09:12:54

app推廣渠道

2019-01-03 11:09:19

2021-05-13 05:25:16

數(shù)據(jù)分析數(shù)分培訓(xùn)大數(shù)據(jù)

2019-04-28 14:24:54

吳亦凡流量數(shù)據(jù)

2024-12-04 13:54:19

pnpm存儲項(xiàng)目

2015-02-25 20:16:06

2018-07-30 15:49:12

2017-09-07 18:45:51

C#

2022-09-30 09:40:39

智能汽車
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號