表 table

表就是關于特定實體的數據集合,這也是關系型數據庫模型的核心麻蹋。

在InnoDB存儲引擎表中跛溉,每張表都有個主鍵(Primary Key),如果在創(chuàng)建表時沒有顯式地定義主鍵,則InnoDB存儲引擎會按如下方式選擇或創(chuàng)建主鍵:
?首先判斷表中是否有非空的唯一索引(Unique NOT NULL)芳室,如果有专肪,則該列即為主鍵。
?如果不符合上述條件堪侯,InnoDB存儲引擎自動創(chuàng)建一個6字節(jié)大小的指針嚎尤。
當表中有多個非空唯一索引時,InnoDB存儲引擎將選擇建表時第一個定義的非空唯一索引為主鍵伍宦。這里需要非常注意的是芽死,主鍵的選擇根據的是定義索引的順序,而不是建表時列的順序

_rowid 可以顯示表的主鍵

InnoDB邏輯存儲結構

從InnoDB存儲引擎的邏輯存儲結構看次洼,所有數據都被邏輯地存放在一個空間中关贵,稱之為表空間(tablespace)。
表空間又由段(segment)卖毁、區(qū)(extent)揖曾、頁(page)組成。頁在一些文檔中有時也稱為塊(block)

如果啟用了innodb_file_per_table的參數亥啦,需要注意的是每張表的表空間內存放的只是數據炭剪、索引和插入緩沖Bitmap頁

其他類的數據,如回滾(undo)信息翔脱,插入緩沖索引頁奴拦、系統(tǒng)事務信息,二次寫緩沖(Double write buffer)等還是存放在原來的共享表空間內碍侦。

插入緩沖Bitmap 插入緩沖頁粱坤?(什么區(qū)別呀)

共享表空間還包含有 undo信息,執(zhí)行rollback后并不會收縮表空間瓷产,會自動判斷這些undo信息是否還需要站玄,如果不需要,則會將這些空間標記為可用空間濒旦,供下次undo使用株旷。(每 10 秒的 full purge)

段 segment

表空間是由各個段組成的,常見的段有數據段尔邓、索引段晾剖、回滾段等。
因為前面已經介紹過了InnoDB存儲引擎表是索引組織的(index organized)梯嗽,因此數據即索引齿尽,索引即數據。
數據段即為B+樹的葉子節(jié)點(Leaf node segment)
索引段即為B+樹的非索引節(jié)點(Non-leaf node segment)
回滾段較為特殊灯节,將會在后面的章節(jié)進行單獨的介紹循头。

數據行基于聚集索引鍵按順序存儲绵估。
非聚集索引不影響數據行的順序

索引組織表(Index Organizied Table)

堆表 and 索引組織表
  • 索引組織表(index organized table, IOT)就是存儲在一個索引結構中的表。存儲在堆中的表是無組織的(也就是說卡骂,只要有可用的空間国裳,數據可以放在任何地方),IOT中的數據則按主鍵存儲和排序全跨。對你的應用來說缝左,IOT表和一個“常規(guī)”表并無二致。
  • 索引組織表的數據按主鍵排序手段被存儲在B-樹索引中浓若,除了存儲主鍵列值外還存儲非鍵列的值渺杉。普通索引只存儲索引列,而索引組織表則存儲表的所有列的值七嫌。
  • 索引組織表一般適應于靜態(tài)表少办,且查詢多以主鍵列苞慢。當表的大部分列當作主鍵列時诵原,且表相對靜態(tài),比較適合創(chuàng)建索引組織表M旆拧(8i以上)
    既然它屬于表绍赛,那么它當然也有建立索引的需求。由于它的索引的結構辑畦,比如說由于索引葉節(jié)點的分裂吗蚌,行所在塊可能會發(fā)生改變,因而建立在IOT上的索引和一般的索引的最大區(qū)別是它存的是IOT的行的邏輯地址纯出,也就是UROWID蚯妇,oracle用這個邏輯rowid來猜這個行所在的塊,如果猜到了暂筝,那么這個urowid是正確的箩言,否則它從這個地址向下遍歷來找這條記錄。
    IOT表的rowid是邏輯上的焕襟,因為IOT表中的行的位置是在不斷變化的(例如插入新的行陨收,有可能帶來其它行的位置移動)

IOT有什么意義呢?使用堆組織表時鸵赖,我們必須為表和表主鍵上的索引分別留出空間务漩。而IOT不存在主鍵的空間開銷,因為索引就是數據它褪,數據就是索引饵骨,二者已經合二為一。但是茫打,IOT帶來的好處并不止于節(jié)約了磁盤空間的占用居触,更重要的是大幅度降低了I/O,減少了訪問緩沖區(qū)緩存(盡管從緩沖區(qū)緩存獲取數據比從硬盤讀要快得多镐确,但緩沖區(qū)緩存并不免費,而且也絕對不是廉價的饼煞。每個緩沖區(qū)緩存獲取都需要緩沖區(qū)緩存的多個閂源葫,而閂是串行化設備,會限制應用的擴展能力)

IOT適用的場合有:

1砖瞧、完全由主鍵組成的表息堂。這樣的表如果采用堆組織表,則表本身完全是多余的開銷块促,因為所有的數據全部同樣也保存在索引里荣堰,此時,堆表是沒用的竭翠。
2振坚、代碼查找表。如果你只會通過一個主鍵來訪問一個表斋扰,這個表就非常適合實現為IOT.
3渡八、如果你想保證數據存儲在某個位置上,或者希望數據以某種特定的順序物理存儲传货,IOT就是一種合適的結構屎鳍。
IOT提供如下的好處:
提高緩沖區(qū)緩存效率,因為給定查詢在緩存中需要的塊更少问裕。
減少緩沖區(qū)緩存訪問逮壁,這會改善可擴縮性。
獲取數據的工作總量更少粮宛,因為獲取數據更快窥淆。
每個查詢完成的物理I/O更少,因為對于任何給定的查詢巍杈,需要的塊更少忧饭,而且對地址記錄的一個物理 I/O 很可能可以獲取所有地址(而不只是其中一個地址,但堆表實現就只是獲取一個地址)

如果經常在一個主鍵或惟一鍵上使用BETWEEN 查詢也是如此秉氧,因為相近的記錄存在一起眷昆,查詢時引入的邏輯IO和物理IO都會更少。

堆表 heap table

堆表(heap table)數據插入時時存儲位置是隨機的汁咏,主要是數據庫內部塊的空閑情況決定亚斋,獲取數據是按照命中率計算,全表掃表時不見得先插入的數據先查到攘滩。

堆表(heap table) 就是一般的表帅刊,獲取表中的數據是按命中率來得到的。沒有明確的先后之分漂问,在進行全表掃描的時候赖瞒,并不是先插入的數據就先獲取女揭。數據的存放也是隨機的,當然根據可用空閑的空間來決定栏饮。

區(qū) extent

區(qū)是由連續(xù)頁組成的空間吧兔,在任何情況下每個區(qū)的大小都為1MB。為了保證區(qū)中頁的連續(xù)性袍嬉,InnoDB存儲引擎一次從磁盤申請4~5個區(qū)境蔼。在默認情況下,InnoDB存儲引擎頁的大小為16KB伺通,即一個區(qū)中一共有64個連續(xù)的頁箍土。

mysql> INSERT INTO t SELECT NULL,REPEAT('a',7000);

新創(chuàng)建表的默認大小是 96KB
在用戶啟用了參數innodb_file_per_talbe后,創(chuàng)建的表默認大小是96KB罐监。區(qū)中是64個連續(xù)的頁吴藻,創(chuàng)建的表的大小至少是1MB才對啊弓柱?其實這是因為在每個段開始時沟堡,先用32個頁大小的碎片頁(fragment page)來存放數據,在使用完這些頁之后才是64個連續(xù)頁的申請吆你。這樣做的目的是弦叶,對于一些小表俊犯,或者是undo這類的段妇多,可以在開始時申請較少的空間,節(jié)省磁盤容量的開銷燕侠。

頁 page

在InnoDB存儲引擎中者祖,常見的頁類型有:
?數據頁(B-tree Node)
?undo頁(undo Log Page)
?系統(tǒng)頁(System Page)
?事務數據頁(Transaction system Page)
?插入緩沖位圖頁(Insert Buffer Bitmap)
?插入緩沖空閑列表頁(Insert Buffer Free List)
?未壓縮的二進制大對象頁(Uncompressed BLOB Page)
?壓縮的二進制大對象頁(compressed BLOB Page)

InnoDB存儲引擎是面向列的(row-oriented),也就說數據是按行進行存放的绢彤。

data page頁默認16kb,當有新索引記錄寫入時,會預留1/16(1kb)空閑空間用于以后的索引記錄寫入

InnoDB存儲引擎數據頁結構

InnoDB數據頁由以下7個部分組成七问。
?File Header(文件頭)
?Page Header(頁頭)
?Infimun和Supremum Records
?User Records(用戶記錄,即行記錄)
?Free Space(空閑空間)
?Page Directory(頁目錄)
?File Trailer(文件結尾信息)

File Header
記錄頁的一些頭信息

Page Header
記錄數據頁的狀態(tài)信息

Infimum和Supremum Record
每個數據頁中有兩個虛擬的行記錄茫舶,用來限定記錄的邊界械巡。Infimum記錄是比該頁中任何主鍵值都要小的值,Supremum指比任何可能大的值還要大的值饶氏。這兩個值在頁創(chuàng)建時被建立讥耗,并且在任何情況下不會被刪除。

User Record 和 Free Space
User Record就是之前討論過的部分疹启,即實際存儲行記錄的內容古程。再次強調,InnoDB存儲引擎表總是B+樹索引組織的喊崖。
Free Space很明顯指的就是空閑空間挣磨,同樣也是個鏈表數據結構雇逞。在一條記錄被刪除后,該空間會被加入到空閑鏈表中茁裙。

Page Directory
存放了記錄的相對位置(注意塘砸,這里存放的是頁相對位置,而不是偏移量)晤锥,有些時候這些記錄指針稱為Slots(槽)或目錄槽(Directory Slots)谣蠢。

由于在InnoDB存儲引擎中Page Direcotry是稀疏目錄,二叉查找的結果只是一個粗略的結果查近,因此InnoDB存儲引擎必須通過recorder header中的next_record來繼續(xù)查找相關記錄眉踱。同時,Page Directory很好地解釋了recorder header中的n_owned值的含義霜威,因為這些記錄并不包括在Page Directory中谈喳。
需要牢記的是,B+樹索引本身并不能找到具體的一條記錄戈泼,能找到只是該記錄所在的頁婿禽。數據庫把頁載入到內存,然后通過Page Directory再進行二叉查找大猛。只不過二叉查找的時間復雜度很低扭倾,同時在內存中的查找很快,因此通常忽略這部分查找所用的時間挽绩。

File Trailer
為了檢測頁是否已經完整地寫入磁盤(如可能發(fā)生的寫入過程中磁盤損壞膛壹、機器關機等),InnoDB存儲引擎的頁中設置了File Trailer部分唉堪。
File Trailer只有一個FIL_PAGE_END_LSN部分模聋,占用8字節(jié)。前4字節(jié)代表該頁的checksum值唠亚,最后4字節(jié)和File Header中的FIL_PAGE_LSN相同链方。將這兩個值與File Header中的FIL_PAGE_SPACE_OR_CHKSUM和FIL_PAGE_LSN值進行比較,看是否一致(checksum的比較需要通過InnoDB的checksum函數來進行比較灶搜,不是簡單的等值比較)祟蚀,以此來保證頁的完整性(not corrupted)。

約束

對于InnoDB存儲引擎本身而言割卖,提供了以下幾種約束:
?Primary Key
?Unique Key
?Foreign Key
?Default
?NOT NULL

約束更是一個邏輯的概念前酿,用來保證數據的完整性,
索引是一個數據結構究珊,既有邏輯上的概念薪者,在數據庫中還代表著物理存儲的方式。

外鍵約束

對于數據的導入操作時剿涮,外鍵往往導致在外鍵約束的檢查上花費大量時間言津。因為MySQL數據庫的外鍵是即時檢查的攻人,所以對導入的每一行都會進行外鍵檢查。但是用戶可以在導入過程中忽視外鍵的檢查悬槽。

分區(qū)表

就訪問數據庫的應用而言怀吻,從邏輯上講,只有一個表或一個索引初婆,但是在物理上這個表或索引可能由數十個物理分區(qū)組成蓬坡。每個分區(qū)都是獨立的對象,可以獨自處理磅叛,也可以作為一個更大對象的一部分進行處理屑咳。

MySQL數據庫的分區(qū)是局部分區(qū)索引,一個分區(qū)中既存放了數據又存放了索引弊琴。而全局分區(qū)是指兆龙,數據存放在各個分區(qū)中,但是所有數據的索引放在一個對象中敲董。目前紫皇,MySQL數據庫還不支持全局分區(qū)。

對表空間的概念好模糊啊腋寨,怎么看都看不明白
段segment聪铺、 區(qū)extent、 頁page(block)
然后數據頁的結構%>_<%

約束
視圖
分區(qū)
看得比較粗糙萄窜,感覺實用性不怎么高呀铃剔。


Jeremy Cole - InnoDB
jeremycole/innodb_ruby
innodb_ruby工具分析innob表空間文件Part-01
innodb_ruby工具分析innob表空間文件Part-02

InnoDB備忘錄 - 數據頁結構
InnoDB備忘錄 - 邏輯存儲

InnoDB 文件系統(tǒng)之文件物理結構

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市脂倦,隨后出現的幾起案子番宁,更是在濱河造成了極大的恐慌,老刑警劉巖赖阻,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異踱蠢,居然都是意外死亡火欧,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門茎截,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苇侵,“玉大人,你說我怎么就攤上這事企锌∮芘ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵撕攒,是天一觀的道長陡鹃。 經常有香客問我烘浦,道長,這世上最難降的妖魔是什么萍鲸? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任闷叉,我火速辦了婚禮,結果婚禮上脊阴,老公的妹妹穿的比我還像新娘握侧。我一直安慰自己,他們只是感情好嘿期,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布品擎。 她就那樣靜靜地躺著,像睡著了一般备徐。 火紅的嫁衣襯著肌膚如雪孽查。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天坦喘,我揣著相機與錄音盲再,去河邊找鬼。 笑死瓣铣,一個胖子當著我的面吹牛答朋,可吹牛的內容都是我干的。 我是一名探鬼主播棠笑,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼梦碗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蓖救?” 一聲冷哼從身側響起洪规,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎循捺,沒想到半個月后斩例,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡从橘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年念赶,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恰力。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡叉谜,死狀恐怖,靈堂內的尸體忽然破棺而出踩萎,到底是詐尸還是另有隱情停局,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站董栽,受9級特大地震影響码倦,放射性物質發(fā)生泄漏。R本人自食惡果不足惜裆泳,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一叹洲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧工禾,春花似錦运提、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至槽畔,卻和暖如春栈妆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背厢钧。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工鳞尔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人早直。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓寥假,卻偏偏與公主長得像,于是被迫代替她去往敵國和親霞扬。 傳聞我的和親對象是個殘疾皇子糕韧,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內容