Mysql技術內幕InnoDB儲存引擎讀書筆記--《四》表

FreeeLinux發表於2017-06-30

4.1InnoDB儲存引擎表型別

如果在建立表時沒有顯示地定義主鍵,那麼InnoDB儲存疫情會按照如下方式選擇或者建立主鍵。

  • 首先表中是否有非空的唯一索引,如果有,則該列即為主鍵
  • 不符合上述條件,InnoDB儲存疫情自動建立一個6個位元組大小的指標

4.2InnoDB邏輯儲存結構

InnoDB儲存引擎的所有資料都被邏輯地存放在表空間中。表空間又由段(segment)、區(extent)、頁(page)組成。

4.2.1表空間

預設情況下InnoDB儲存引擎有一個共享表空間ibdata1,即所有資料都放在這個表空間內。如果我們啟用了引數innodb_file_per_table,則每張表內的資料可以單獨放到一個表空間內。

對於啟用了innodb_file_per_table引數選項,每張表的表空間記憶體放的只是資料、索引和插入緩衝,其他類的資料,如撤銷(Undo)資訊、系統事務資訊、二次寫緩衝等還是存放在原來的共享表空間內。

4.2.2段

表空間是由分散的頁和段組成。

4.2.3區

區是由64個連續的頁組成,即每個區的大小為1MB。對於大的資料段,InnoDB儲存引擎最多每次可以申請4個區,以此來保證資料的順序效能。

4.2.4頁

InnoDB的頁的大小為16KB。

4.2.5行

InnoDB儲存引擎是面向行的,也就是說資料的存放按行進行存放。每個頁存放的行記錄也是有硬性定義的,最多允許存放16KB/2~200行的記錄,即7992行記錄。

4.3InnoDB物理儲存結構

從物理意義上來看,InnoDB表由共享表空間、日誌檔案組(更準確地說,應該是Redo檔案組)、表結構定義檔案組成。若將innodb_file_per_table設定為on,則每個表將獨立地產生一個表空間檔案,以idb結尾,資料、索引、表的內部資料字典資訊都將儲存在這個單獨的表空間檔案中。表結構定義檔案以frm結尾。這個是以與儲存引擎無關的,任何儲存引擎的表結構定義檔案都一樣,為.frm檔案。

4.4InnoDB行記錄格式

4.4.1Compact行記錄格式

Compact行設計目標是能高效存放資料。簡單來說,如果一個頁中存放的行資料越多,其效能就越高。

變長欄位長度列表 NULL標誌位 記錄頭資訊 列1資料 列2資料 ……

Compact行格式的首部是一個非NULL變長欄位長度列表,而且是按照列的順序逆置放置的。當列的長度小於255位元組,用1位元組表示,若大於255個位元組,用2個位元組表示,變長欄位的長度最大不可以超過2個位元組。第二個部分是NULL標誌位,該位知識了該行資料中是否有NULL值,用1表示。該部分所佔的位元組應該為bytyes。接下去的部分是記錄頭資訊,固定佔用5個位元組。最後的部分就是實際儲存的每個列的資料,需要特別注意的是,NULL值不佔該部分任何資料,即NULL除了戰友NULL標誌位,還有兩個隱藏列,事務ID列和回滾指標列,分別為6個位元組和7個位元組的大小。若InnoDB沒有定義Primary Key,每行會增加一個6位元組的RowId列。

由此可以算出Mysql的varchar最大長度為65532個位元組,65535-1(NULL標誌)-2(變長欄位)=65532。

Redundant行記錄格式

Redundant是Mysql5.0之前的,不過多介紹。

4.4.3行溢位資料

對於大多數的情況,BLOB的行資料還是會發生行溢位,實際資料儲存在BLOB頁中,資料頁只儲存資料的前768個位元組。

4.4.5char的行結構儲存

在InnoDB引擎內部對於char型別在多位元組字符集型別(如utf8)的儲存,char很明確的被視為了變長型別,對於未能佔滿長度的字元還是填充長度。可以說,在多位元組字符集的情況下,char和varchar的行儲存基本是沒有區別的。

4.5InnoDB資料頁結構

InnoDB資料頁由以下七個部分組成:

File Header Page Header Infimum+Supremum Records User Records Free Space Page Directory File Trailer

4.5.1File Header

File Header用來記錄頁的一些頭資訊。

  • FILE_PAGE_SPACE_OR_CHKSUM,該值代表頁的checksum值。
  • FIL_PAGE_OFFSET:表空間中頁的偏移值。
  • FIL_PAGE_PREV,FIL_PAGE_NEXT:當前頁的上一個頁以及下一個頁。B+ Tree特性據定了葉子節點必須是雙向列表。
  • FIL_PAGE_LSN:該值代表該頁最後被修改的日誌序列位置LSN(Log Sequence Nuber)。
  • FIL_PAGE_TYPE:頁的型別,通常有:B+樹頁節點,Undo Log頁,索引節點,Insert Buffer空閒列表,該頁為最新分配,Insert Buffer點陣圖這幾種意思。
  • FIL_PAGE_FILE_FLUSH_LSG:該值僅在資料檔案中的一個頁中定義,代表檔案至少被更新到了該LSN值。
  • FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID:該值代表頁面屬於哪個表空間。

4.5.2Page Header

  • PAGE_N_DIR_SLOTS:在Page Directory(頁目錄)中的Slot(槽)數。
  • PAGE_HEAP_TOP:堆中第一個記錄的指標。
  • PAGE_N_HEAP:堆中的記錄數。
  • PAGE_FREE:指向空閒列表的首指標。
  • PAGE_GARBAGE:已刪除記錄的位元組數,即行記錄結構中,delete flag為1的記錄大小的總數。
  • PAGE_LAST_INSERT:最後插入記錄的位置。
  • PAGE_DIRECTION:最後插入的方向。
  • PAGE_N_DIRECTION:宇哥方向連續插入記錄的數量。
  • PAGE_N_RECS:該頁中記錄的數量。
  • PAGE_MAX_TRX_ID:修改當前頁的最大事務ID,注意該值僅在Secondary Index定義。
  • PAGE_LEVEL:當前頁在索引樹中的位置,0x00代表葉節點。
  • PAGE_IDNEX_ID:當前頁屬於哪個索引ID。
  • PAGE_BTR_SEG_LEAF:B+樹的葉節點中,檔案段的首指標位置。注意該值僅在B+樹的Root頁中定義。
  • PAGE_BTR_SEG_TOP:B+樹的非葉節點中,檔案段的首指標位置。注意該值僅在B+樹的Root頁中定義。

4.5.3Infimum和Supremum記錄

在InnoDB儲存引擎中,每個資料頁中有兩個虛擬的行記錄,用來限定記錄的邊界。Supremum和Infimum分別是主鍵值得上界和下界,這兩個值在頁建立時被建立,並且在任何情況下不會被刪除。

4.5.4User Records與FreeSpace

User Records就是之前我們討論過的部分,即實際儲存行記錄的內容。
Free Space指的就是空閒空間,同樣也是個連結串列資料結構。當一條記錄被刪除後,該空間會被加入空閒連結串列中。

4.5.5Page Directory

Page Directory(頁目錄)中存放了記錄的相對位置。需要記住,B+樹索引本身並不能找到具體的一條記錄,B+樹索引能找到的只是該記錄所在的頁。資料庫把頁載入記憶體,然後通過Page Directory再進行二分查詢。

4.5.6File Trailer

用來保證頁能夠完整的寫入磁碟,來作比較以此來保證頁的完整性。

4.7約束

外來鍵

一般來說,我們稱被引用的表為父表,另一個引用的表為子表。外來鍵定義為:ON DELETE和ON UPDATE表示父表做DELTE和UPDATE操作時相應的子表所做的操作。可定義子表操作有:

  • CASCADE:當父表發生DELETE或UPDATE操作時,相應的子表中的資料也進行同樣操作。
  • SET NULL:當父表發生DELETE或UPDATE操作時,相應的子表中的資料被設定為NULL值。當然,子表中的相應的列必須允許NULL值。
  • NO ACTION:當父表發生DELETE或UPDATE操作時,剖出錯誤,不允許這類操作發生。*如果定義外來鍵時沒有指定ON DELETE或ON UPDATE,這就是預設的外來鍵設定。

4.8檢視

檢視的主要用途之一是被用作一個抽象裝置,特別是對於一些應用程式,程式本身不需要關心基表的結構,只需要按照檢視定義來獲取資料或者更新資料。因此,檢視同時在一定程度上起到一個安全層的作用。

Mysql本身不支援物化檢視,需要採用SELECT然後INSERT類似這種的方式匯入檢視的資料到表中。

4.9分割槽

Mysql分割槽實際上就是將一張表的資料分成多個部分,如果對於大的資料量,分割槽讓我們可以快速定位資料位於那一部分,那麼就直接排除掉了其他部分的資料,所以分割槽有利於查詢效能。

查詢未新增索引的列,分割槽比未分割槽的錶快很多倍;查詢已新增索引的列,分割槽稍由於未分割槽的表。

分割槽可參考該文章:深入解析MySQL分割槽(Partition)功能

相關文章