前言
索引是mysql資料庫中很重要的組成部分,也是程式設計師最關注的部分,索引的目的主要在於提高查詢的效率。可以模擬於字典中的目錄。查詢字典中的內容的同時,可以根據目錄查詢資料的存放位置,從而提取到資料。mysql 支援多種儲存引擎,我們只針對innodb下面的b+tree索引進行學習
索引的原理
在生活中隨處可見索引的列子,比如上面提到的圖書的目錄,車次表,原理都是一樣的通過不斷的縮小查詢範圍的資料,來獲取結果。資料庫也是一樣的,但是顯然要複雜很多,因為我們不僅僅面著著等值查詢(=),還有範圍查詢(, between and , in ),模糊匹配 (like), 並集的查詢(or) 等等。
基於這些問題,資料庫應該怎麼來設計應對這樣的問題?基於資料庫的實現,我們的資料是儲存在磁碟上的,為了提高效能,每次我們又需要把部分資料載入到記憶體中計算,我們知道訪問磁碟的成本大概是訪問記憶體成本的10萬倍左右。
磁碟io跟預讀取
這裡補充一點計算機的基礎知識
硬碟的工作原理
現代硬碟尋道都是採用chs(cylinder head sector)的方式,硬碟讀取資料時,讀寫磁頭沿徑向移動,移到要讀取的扇區所在磁軌的上方,這段時間稱為尋道時間(seek time)。因讀寫磁頭的起始位置與目標位置之間的距離不同,尋道時間也不同。目前硬碟一般為2到30毫秒,平均約為9毫秒。磁頭到達指定磁軌後,然後通過碟片的旋轉,使得要讀取的扇區轉到讀寫磁頭的下方,這段時間稱為旋轉延遲時間(rotational latencytime)
機械硬碟,每次讀取的時候都是依靠機械運動,每次讀取時間都分為尋道時間、旋轉延遲、傳輸時間三個部分。尋道時間只的磁頭尋找到磁軌需要的時間,主流的磁碟大概是在5ms以內;旋轉延遲簡單理解就是我們經常說的磁碟的轉速,eg:7200轉,指的是7200/min,等於120/sec ,旋轉的延時就是1/120/2(一般都將磁碟旋轉週期的一半定義為旋轉延遲)約等 4.17ms,傳輸的時間指將資料從磁碟讀取或者寫入時間,一般在零點幾毫秒,可以忽略。通過以上理論計算 ,平均訪問一次磁碟io的時間大概是在9ms左右,聽起來不錯但是針對資料庫隨隨便便上百萬,千萬級別的的資料,每次io需要9ms的時間,顯然是無法承受的。
ssd的技術發展,取代了傳統的機械硬碟,採用了快閃儲存器技術,大大提高了磁碟的讀寫能力。
innodb架構
master thread
主要是負責將緩衝池的資料非同步重新整理到磁碟,保障資料的一致性,包括髒頁的重新整理,合併插入緩衝(insert buffer)、回滾頁(undo page)的**等。
io thread
innodb 儲存引擎中大量使用了aio(async io)處理io的請求,這樣可以極大的提高資料庫的處理效能。io thread(insert buffer thread; log thread ; read thread ; write thread)
purge thread
事務被提交後,使用的undo log 可能不再需要,因此需要 purge thread 來**已經使用並分配的undo 頁。
page cleaner thread
1.2 版本之後引入,將之前版本中的髒頁資料重新整理操作,用乙個單獨的執行緒來操作,目的是為了減輕 master thread的工作,以及使用者查詢執行緒的阻塞。
mysql資料頁結構分析
page 是innodb儲存引擎用於管理資料的最小磁碟單位。常見的頁型別,有資料頁,undo頁,系統頁,事務資料頁等。我們主要研究一下資料頁跟行記錄資料結構。
從上到下依次為:tablespace(表空間,ibd檔案)、segment(段,乙個索引2個段)、extent(區,預設1mb,1 extent=64page)、 page (頁,預設16kb,磁碟管理最小單位)
每個page占用了16kb,64個連續的page占用1mb叫做extent, 多個extent 組合在一起就是乙個表空間,也叫做表檔案。
page跟row的結構。
page邏輯結構
幾個基本概念
page的預設大小是16kb,每個page用乙個32位的數字進行標記,一共有2^32個page,每個表空間有64t的容量(16*2^32/1024/1024/1024=64tb)
每個page都乙個offerset,page0 的offerset = 0 ,page1 的offerset = 16384(16kb),以此類推
每個page有個38位元組的位元組頭,跟8位元組的尾,有興趣的可以研究下
page的邏輯儲存結構圖
如圖所示:每個page 儲存著pre_head和next_head 的指標資訊;page head裡還儲存著page的型別和page的序號等資訊。
頁的中間儲存著資料記錄,其中第一條記錄為系統記錄,supermum 儲存資料的尾指標資訊,infimum 儲存資料的頭指標資訊。user record是單鏈表的形式儲存。
從上面簡單的邏輯儲存來看,其實可以發現資料庫的儲存引擎本質上按照乙個檔案系統來設計的。
mysql記錄儲存
頁頭記錄頁面的控制資訊,一共佔56位元組,包含左右相鄰頁的指標,以及頁面空間的使用情況。
虛記錄(infimum+supremum records)最小虛記錄以及最大虛記錄
兩個固定位置儲存的記錄,本身並不儲存資料。
最大虛記錄,比頁內最大的主鍵還大
最小虛記錄,比頁內最小的主鍵還小
記錄堆(record heap) 對應 user record
有效記錄 -> 索引正常使用的記錄
已刪除記錄-> 表示索引已經刪除的記錄,不使用的記錄,隨著記錄的更新和刪除越來越頻繁,記錄堆中的已刪除的記錄將會越多,出現記憶體空洞和碎片。這些已刪除的記錄連線起來,就會形成頁面的自由空間鍊錶。
未分配空間: 指頁面未使用的儲存空間,隨著頁面的不斷使用,未分配空間將會越來越小。當新插入一條記錄時,首先嘗試從自由空間鍊錶,獲得合適的儲存位置,(空間足夠),如果沒有滿足的,就會在未分配的空間中申請。
頁尾(page tailer): 頁面的最後部分,佔8個位元組,主要儲存頁面的校驗資訊。
mysql資料庫蛛 MySQL效能優化
mysql的配置檔案 my.cnf 的優化 配置檔案 結合my.cnf 檔案,只列出其中 mysqld 段落中的內容,其他段落內容對 mysql 執行效能影響甚微,因而姑且忽略。介紹一些優化引數。1.mysqld 2.port 3306 3.socket tmp mysql.sock 4.skip ...
mysql資料庫索引名 Mysql資料庫索引簡介
1.什麼是索引?資料庫索引是表中的乙個特殊的資料結構,存放的記錄的快速檢索的值,也稱為目錄,被儲存在乙個地方,所以索引是乙個存在的檔案,並不是儲存在記憶體中 索引的存在是為了在查詢時,可以直接通過查詢索引找到那一條記錄所在的位置,而不是逐一的去檢索,大大的提高的查詢的效率 那麼是不是每一列都建立乙個...
mysql資料庫效能資料 MYSQL資料庫效能優化
1.選取最適用的字段屬性 表中字段的寬度設得盡可能小 char 的上限為 255 位元組 固定占用空間 varchar 的上限 65535 位元組 實際占用空間 text 的上限為 65535。盡量把字段設定為 not null,執行查詢的時候,資料庫不用去比較 null 值。2.使用連線 join...