2017-08-27 40 views
2

在MySQL中(或者我應該說:用MySQL的InnoDB引擎) - 空值是如何表示的?即如果允許列具有NULL s,那麼表格(或者如果它在記錄級別上是單個記錄)的表示如何改變?MySQL/InnoDB如何在內部表示NULL值?

如果不同的列數據類型不同 - 要麼解釋表示NULL的各種方法,要麼選擇一種數據類型(例如INT)。

回答

2

參考

https://dev.mysql.com/doc/refman/5.7/en/innodb-physical-record.html

行情和解讀

ROW_FORMAT=REDUNDANT

一個SQL NULL值保留一個或記錄中的目錄中的兩個字節。除此之外,如果存儲在可變長度列中,則SQL NULL值在記錄的數據部分保留零字節。在固定長度的列中,它在記錄的數據部分中保留列的固定長度。爲NULL值保留固定空間使得能夠將列從NULL更新爲非NULL值,而不導致索引頁的碎片化。

也就是說,1位/列用於NULL,不節省數據。

ROW_FORMAT=COMPACT

記錄標題的可變長度部分包含用於指示NULL列的位向量。如果索引中可以爲NULL的列數爲N,則該位向量佔用CEILING(N/8)個字節。 (例如,如果有9到15列的任何地方可以爲NULL,則位向量使用兩個字節。)NULL的列不佔用此向量中的位以外的空間。標題的可變長度部分也包含可變長度列的長度。每個長度需要一個或兩個字節,具體取決於列的最大長度。如果索引中的所有列都不是NULL並且具有固定長度,則記錄標頭不包含可變長度部分。

也就是說,1位/列,零空間的數據。

我懷疑,沒有證據,DYNAMICCOMPRESSED就像COMPACT

柱長

每一列都具有在它前面的一個1-或2-字節長度。 1或2的選擇基於最大電位列寬。 (注意:儘管LONGTEXT需要4個字節的長度,但「長度」實際上是指存儲在記錄中的數量,而不是溢出。)

溢出存儲

雖然我的話題,在這裏是什麼與「長」串/斑點發生的一些信息 - 無論是在記錄或存儲在別處:

  • < = 40字節(在給定列中):存儲在記錄中。
  • 如果整個記錄適合大約8KB:存儲在記錄中。
  • 否則,和COMPACT:768 + 20長列
  • 否則,和DYNAMICCOMPRESSED:20長列

「768」 是指該第一768個字節的文本/斑點的存儲在記錄中; 「20」表示一個20字節的「指針」,指向其餘(或全部)存儲的位置。

KEY_BLOCK_SIZE控制聚集索引中存儲了多少列數據,以及溢出頁面上放置了多少列數據。

(我離開REDUNDANT出來的,因爲我沒有細節。)拇指

沒有爲每個InnoDB的行20-30個字節的開銷的

規則。

B樹(包括數據InnoDB的,再加上每個副指數)在重力作用下,以69%爲完全分裂塊等

「Data_free」是遠遠不完全;不要相信它。

MyISAM在空間上非常簡潔;計算MyISAM表的空間很容易。從那裏,乘以2-3來獲得InnoDB所需的空間。 (也有例外,通常涉及到MyISAM碎片,PK集羣等)

+0

...在磁盤存儲和內存中表示之間是相同的嗎?即從磁盤加載數據時是否發生任何解析/格式/佈局更改? – einpoklum

+0

緩存(在RAM中)和磁盤之間的存儲是一樣的,但有一個例外:'ROW_FORMAT = COMPRESSED'在磁盤上壓縮,但在緩存中壓縮和解壓縮 - 使得它在我看來不適用於大多數情況。該壓縮是在塊級上的(有點),而不是單個的列。 –

1

這僅適用於COMPACT(除非您訪問字典表,否則REDUNDANT僅適用於歷史原因)。 對於每個NULL-able列,NULLS頭中有一位。

如果表中沒有可NULL字段NULLs標頭大小爲零。

如果列值爲NULL,則該位被設置並且記錄數據中沒有值。

如果列值不爲NULL,則該位未設置,列值存儲在記錄的數據中。

Record in COMPACT format