mysql技術內幕(四)表

表就是關於特定實體的數據集合,這也是關係型數據庫模型的核心。

4.1 索引組織表

  在InnoDB 存儲引擎中,表都是根據主鍵順序組織存放的,這種存儲方式的表稱爲索引組織表(index organized table) 。在InnoDB 存儲引擎表中,每張表都有個主鍵(Primary Key ) ,如果在創建表時沒有顯式地定義主鍵,則InnoDB 存儲引擎會按如下方式選擇或創建主鍵:

  • 首先判斷表中是否有非空的唯一索引( Unique NOT NULL) ,如果有,則該列即爲主鍵。
  • 如果不符合上述條件, InnoDB 存儲引擎自動創建一個6 字節大小的指針。

   當表中有多個非空唯一索引時, InnoDB 存儲引擎將選擇建表時第一個定義的非空唯一索引爲主鍵。這裏需要非常注意的是,主鍵的選擇根據的是定義索引的順序,而不是建表時列的順序。

4.2 InnoDB 邏輯存儲結構

  從InnoDB 存儲引擎的邏輯存儲結構看,所有數據都被邏輯地存放在一個空間中,稱之爲表空間(tablespace) 。表空間又由段(segment) 、區(extent) 、頁(page) 組成。頁在一些文檔中有時也稱爲塊( block ) , InnoDB 存儲引擎的邏輯存儲結構大致如圖
在這裏插入圖片描述

4.2.1 表空間

  表空間可以看做是InnoDB 存儲引擎邏輯結構的最高層, 所有的數據都存放在表空間中。在默認情況下InnoDB 存儲引擎有一個共享表空間ibdata1 ,即所有數據都存放在這個表空間內。如果用戶啓用了參數innodb_ file per_table, 則每張表內的數據可以單獨放到一個表空間內。

  如果啓用了innodb_file_per_table的參數,需要注意的是每張表的表空間內存放的只是數據、索引和插人緩衝Bitmap 頁,其他類的數據, 如回滾( undo ) 信息,插入緩衝索引頁、系統事務信息, 二次寫緩衝( Double write buffer) 等還是存放在原來的共享表空間內。這同時也說明了另一個問題: 即使在啓用了參數innodb_file_per_table 之後,共享表空間還是會不斷地增加其大小。

4.2.2 段

  表空間是由各個段組成的,常見的段有數據段、索引段、回滾段等。
  InnoDB 存儲引擎表是索引組織的(index organized) ,因此數據即索引,索引即數據。那麼數據段即爲B+ 樹的葉子節點(圖4-1 的Leafnode segment) ,
索引段即爲B+ 樹的非索引節點(圖4-1 的Non-leaf node segment) 。回滾段較爲特殊。在InnoDB 存儲引擎中,對段的管理都是由引擎自身所完成, DBA 不能也沒有必要對其進行控制。這和Oracle 數據庫中的自動段空間管理(ASSM) 類似,從一定程度上簡化了DBA 對於段的管理。

4.2.3 區

  區是由連續頁組成的空間,在任何情況下每個區的大小都爲1MB 。爲了保證區中頁的連續性, InnoDB 存儲引擎一次從磁盤申請4~5個區。在默認情況下,InnoDB 存儲
引擎頁的大小爲16KB,即一個區中一共有64個連續的頁。lnnoDB 1.0.x 版本開始引入壓縮頁,即每個頁的大小可以通過參數設置爲2K 、4K 、8K ,因此每個區對應頁的數盤就應該爲512 、256 、128

4.2.4 頁

  InnoDB 有頁(Page) 的概念〈也可以稱爲塊),頁是InnoDB磁盤管理的最小單位。在lnnoDB 存儲引擎中,默認每個頁的大小爲16KB。 而從InnoDB 1 .2.x 版本開始, 可以通過參數innodb_page_size 將頁的大小設置爲4K、8K、16K。若設置完成, 則所有表中頁的大小都爲innodb_page_size ,不可以對其再次進行修改。除非通過mysqldump 導入和導出操作來產生新的庫。
  在InnoDB 存儲引擎中,常見的頁類型有:

  • 數據頁( B-tree Node )
  • undo 頁(undo Log Page)
  • 系統頁(System Page)
  • 事務數據頁( Transaction system Page)
  • 插入緩衝位圖頁(Insert Buffer Bitmap)
  • 插入緩衝空閒列表頁( Insert Buffer Free List)
  • 未壓縮的二進制大對象頁(Uncompressed BLOB Page)
  • 壓縮的二進制大對象頁(compressed BLOB page)

4.2.5 行

  InnoDB 存儲引擎是面向列的(row-oriented) ,也就說數據是按行進行存放的。每個頁存放的行記錄也是有硬性定義的,最多允許存放16KB / 2-200 行的記錄,即7992 行記錄。

4.3 InnoDB 行記錄格式

  記錄是以行的形式存儲的。這意味着頁中保存着表中一行行的數據。InnoDB 存儲引擎提供了Compact 和Redundant 兩種格式來存放行記錄數據。

4.3.1 Compact 行記錄格式

  Compact 行記錄是在MySQL 5.0 中引人的,其設計目標是高效地存儲數據。簡單來說,一個頁中存放的行數據越多,其性能就越高。

4.3.2 Redundant 行記錄格式

Redundant是MySQLS .O 版本之前InnoDB 的行記錄存儲方式. MySQL 5.O 支持Redundant是爲了兼容之前版本的頁格式。

4.3.3 行溢出數據

  InnoDB 存儲引擎可以將一條記錄中的某些數據存儲在真正的數據頁麗之外。一般認爲BLOB 、LOB 這類的大對象列類型的存儲會把數據存放在數據頁面之外。但是,這個
理解有點偏差, BLOB 可以不將數據放在溢出頁面,而且即便是VARCHAR 列數據類型,依然有可能被存放爲行溢出數據。
首先對VARCHAR 數據類型進行研究 MySQL 數據庫的VARCHAR 類型可以存放65 535 字節。但是,這是真的嗎?通過實際測試發現能存放VARCHAR類型的最大長度爲65532。

到表空間中有一個數據頁節點B-tree Node ,另外有4 個未壓縮的二進制大對象頁Uncompressed BLOB Page,在這些頁中才真正存放了65532 字節的數據。實際存放的數據都在BLOB 頁中

在這裏插入圖片描述

4.4 InnoDB 數據頁結構

   頁是InnoDB 存儲引擎管理數據庫的最小磁盤單位。頁類型爲B-tree Node的頁存放的即是表中行的實際數據。
   InnoDB 數據頁由以下7個部分組成

  • File Header (文件頭〉
  • Page Header (頁頭〉
  • Infimun 和Supremum Records
  • User Records (用戶記錄,即行記錄)
  • Free Space ( 空閒空間〉
  • Page Dircctory (頁目錄)
  • File Trailer (文件結尾信息〉

   其中File Header、Page Header、File Trailer 的大小是固定的,這些空間用來標記該頁的一些信息,如Checksum ,數據頁所在B+ 樹索引的層數
等。User Records、Free Space、Page Directory 這些部分爲實際的行記錄存儲空間,因此大小是動態的。

圖1

4.5 Named File Formats 機制

  略

4.6 約束

4.6.1 數據完整性

   關係型數據庫系統和文件系統的一個不同點是, 關係數據庫本身能保證存儲數據的完整性,不需要應用程序的控制,而文件系統一般需要在程序端進行控制。當前幾乎所有的關係型數據庫都提供了約束(constraint) 機制,該機制提供了一條強大而簡易的途徑來保證數據庫中數據的完整性。一般來說,數據完整性有以下三種形式:實體完整性保證表中有一個主鍵。在InnoDB 存儲引擎表中,用戶可以通過定義Primary Key 或Unique Key 約束來保證實體的完整性。用戶還可以通過編寫一個觸發器來保證數據完整性。

   域完整性保證數據每列的值滿足特定的條件。在InnoDB 存儲引擎表中,域完整性可以通過以下幾種途徑來保證:

  • 選擇合適的數據類型確保一個數據值滿足特定條件。
  • 外鍵( Foreign Key) 約束。
  • 編寫觸發器。
  • 還可以考慮用DEFAULT 約束作爲強制域完整性的一個方面。

參照完整性保證兩張表之間的關係。InnoDB 存儲引擎支持外鍵,因此允許用戶定義外鍵以強制j參照完整性,也可以通過編寫觸發器以強制執行。
對於InnoDB 存儲引擎本身而言, 提供了以下幾種約束:

  • Primary Key
  • Unique Key
  • Foreign Key
  • Default
  • NOT NULL
    在這裏插入圖片描述

4.6.2 約束的創建和查找

4.6.3 約束和索引的區別

Primary Key 和Unique Key 的約束有什麼區別呢?
  的確,當用戶創建了一個唯一索引就創建了一個唯一的約束。但是約束和索引的概念還是有所不同的, 約束更是一個邏輯的概念, 用來保證數據的完整性,而索引是一個數據結構,既有邏輯上的概念, 在數據庫中還代表着物理存儲的方式。

4.6.4 對錯誤數據的約束

  在某些默認設置下, MySQL 數據庫允許非法的或不正確的數據的插入或更新,只或者可以在數據庫內部將其轉化爲一個合法的值,如向NOT NULL 的字段插入一個NULL值, MySQL 數據庫會將其更改爲0 再進行插入, 因此數據庫本身沒有對數據的正確性進行約束。

4.6.5 ENUM 和SET 約束

  MySQL 數據庫不支持傳統的CHECK 約束,但是通過ENUM 和SET 類型可以解決部分這樣的約束需求。例如表上有一個性別類型,規定域的範圍只能是male 或female ,在這種情況下用戶可以通過ENUM 類型來進行約束。

4.6.6 觸發器與約束

4.6.7 外鍵約束

外鍵用來保證參照完整性,MySQL 數據庫的MyISAM存儲引擎本身並不支持外鍵,對於外鍵的定義只是起到一個註釋的作用

4.7 視圖

4.8 分區表

4.8.1 分區概述

   分區的過程是將一個表或索引分
解爲多個更小、更可管理的部分。就訪問數據庫的應用而言,從邏輯上講,只有一個表或一個索引,但是在物理上這個表或索引可能由數十個物理分區組成。每個分區都是獨立的對象,可以獨向處理,也可以作爲一個更大對象的一部分進行處理。MySQL 數據庫支持的分區類型爲水平分區,並不支持垂直分區。此外, MySQL數據庫的分區是局部分區索引,一個分區中既存放了數據又存放了索引。而全局分區是
指,數據存放在各個分區中,但是所有數據的索引放在一個對象中。目前, MySQL 數據庫還不支持全局分區。

   分區可能會給某些SQL 語句性能帶來提高,但是分區主要用於數據庫高可用性的管理。在OLTP 應用中,對於分區的使用應該非常小心。總之,如果只是一昧地使用分區,而不理解分區是如何工作的,也不清楚你的應用如何使用分區,那麼分區極有可能會對性能產生負面的影響。當前MySQL 數據庫支持以下幾種類型的分區。

  • RANGE 分區:行數據基於屬於一個給定連續區間的列值被放入分區。MySQL 5.5
    開始支持隊NGECOLUMNS 的分區。
  • LIST 分區:和RANGE 分區類型,只是LIST 分區面向的是離散的值。MySQL 5.5
    開始支持LIST COLUMNS 的分區。
  • HASH 分區: 根據用戶自定義的表達式的返回值來進行分區,返回值不能爲負數。
  • KEY 分區:根據MySQL 數據庫提供的哈希函數來進行分區。

  不論創建何種類型的分區,如果表中存在主鍵或唯一索引時,分區列必須是唯一索引的一個組成部分,因此下面創建分區SQL 語句會產生錯誤。

   分區啓用後會根據分區列數據存在不同的物理文件中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章