最近讀了《數據庫索引設計與優化》一書。
直呼內行,如下是讀書筆記。mysql
新插入的錶行所在的表頁的索引是聚簇索引。
若索引行的順序和錶行的索引具備強關聯性可說這個索引是彙集的。可是不必定是聚簇索引。
一個表只容許有一個聚簇索引。在某個特定時間可能會有多個索引是彙集的。sql
表和索引行都被存儲在頁中。頁的大小通常爲4/8 KB. 緩衝池和IO的活動都是基於頁的。
頁的大小決定了一頁能夠存儲多少個索引行,錶行。數據庫
索引頁和表頁都是在頁內存儲數據,差別是一個存儲的是data數據,一個存儲的是索引數據。若索引頁存儲的是非聚簇索引,那麼連續的索引頁指向的是非連續的data數據頁。此時全索引掃描是順序IO,對指向的數據的掃描是隨機Io.緩存
聚簇索引頁是連續的所指向的data數據頁也是連續的。經過聚簇索引掃描錶行是順序IO.異步
內存緩存區,一般很是大,能夠存儲成千上萬的頁。MySQL緩衝區的目的是將經常使用的數據緩存起來避免頻繁的磁盤IO帶來的性能損耗。每個DBMS會根據對象類型(表和索引)及頁的狀況擁有多個緩衝區。性能
能夠分爲順序IO和隨機IO優化
順序IO: 指讀寫操做的訪問地址連續。在順序IO訪問中,HDD所需的磁道搜索時間顯着減小,由於讀/寫磁頭能夠以最小的移動訪問下一個塊。數據備份和日誌記錄等業務是順序IO業務。
隨機IO:指讀寫操做時間連續,但訪問地址不連續,隨機分佈在磁盤的地址空間中。
mysql在處理IO的過程當中一般都會伴隨着預讀取,局部預讀原理告訴咱們,當計算機訪問一個地址的數據時候,與他相鄰的地址的數據也有較大概率訪問到因此一次io會把相鄰頁的數據也加載到緩存區當中去。設計
對一頁或者多個連續頁一次數據讀取咱們認爲是一次IO. 一次隨機IO的耗時大概是10ms。
每次讀取數據的時間大體可分爲指針
其中尋道時間和旋轉時間稱爲服務時間。同數據庫緩衝區同樣,磁盤也有緩衝區,若數據存在於磁盤緩衝區,尋道時間和旋轉時間都可省略,IO時間將會下降在1ms左右。日誌
如下都是順序IO
通常DBMS會知道哪些索引和表頁須要被順序的讀取,且能識別出不在緩衝區的頁,而後發出多頁的一次IO請求。對於平均4K的表頁來講在40MB/s的讀取速度下,順序IO的耗時可能爲0.1ms.
且一般伴隨着預讀,在須要所需數據前將一部分數據讀取到緩衝區當中去。
前提:
假設在一個索引上添加一行須要耗時10ms當前狀況不考慮異步寫 那麼索引的新增須要找到對應的索引頁的插入位置,對於非聚簇索引這個位置一般不是最後一個索引頁末尾,尋找對於的索引頁是一個隨機IO過程,能夠認爲是估算值10ms
問題:
分析以上狀況下隨機IO次數:
被修改的葉子頁最終都會落到磁盤上去,因爲數據庫的寫是異步的,因此寫不會影響事務時間,可是寫會增長磁盤的負載,若是一張表的插入較高的話,磁盤負載可能會變成限制索引數量的主要問題。
若是一個表中有千萬行以上的數據,索引磁盤空間的成本可能會成爲一個限制因素,每一次數據的寫入都須要增長對應索引的空間。