索引設計與優化-讀書筆記-1

最近讀了《數據庫索引設計與優化》一書。
直呼內行,如下是讀書筆記。mysql

聚簇索引

新插入的錶行所在的表頁的索引是聚簇索引。
若索引行的順序和錶行的索引具備強關聯性可說這個索引是彙集的。可是不必定是聚簇索引。
一個表只容許有一個聚簇索引。在某個特定時間可能會有多個索引是彙集的。sql

索引頁和表頁

表和索引行都被存儲在頁中。頁的大小通常爲4/8 KB. 緩衝池和IO的活動都是基於頁的。
頁的大小決定了一頁能夠存儲多少個索引行,錶行。數據庫

索引頁和表頁都是在頁內存儲數據,差別是一個存儲的是data數據,一個存儲的是索引數據。若索引頁存儲的是非聚簇索引,那麼連續的索引頁指向的是非連續的data數據頁。此時全索引掃描是順序IO,對指向的數據的掃描是隨機Io.緩存

聚簇索引頁是連續的所指向的data數據頁也是連續的。經過聚簇索引掃描錶行是順序IO.異步

緩衝區

內存緩存區,一般很是大,能夠存儲成千上萬的頁。MySQL緩衝區的目的是將經常使用的數據緩存起來避免頻繁的磁盤IO帶來的性能損耗。每個DBMS會根據對象類型(表和索引)及頁的狀況擁有多個緩衝區。性能

磁盤IO

能夠分爲順序IO和隨機IO優化

順序IO: 指讀寫操做的訪問地址連續。在順序IO訪問中,HDD所需的磁道搜索時間顯着減小,由於讀/寫磁頭能夠以最小的移動訪問下一個塊。數據備份和日誌記錄等業務是順序IO業務。
隨機IO:指讀寫操做時間連續,但訪問地址不連續,隨機分佈在磁盤的地址空間中。
mysql在處理IO的過程當中一般都會伴隨着預讀取,局部預讀原理告訴咱們,當計算機訪問一個地址的數據時候,與他相鄰的地址的數據也有較大概率訪問到因此一次io會把相鄰頁的數據也加載到緩存區當中去。設計

隨機IO耗時估算

對一頁或者多個連續頁一次數據讀取咱們認爲是一次IO. 一次隨機IO的耗時大概是10ms。
每次讀取數據的時間大體可分爲指針

  1. 排隊等待時間:可能發生的排隊時間
  2. 尋道時間: 是指磁盤 磁臂震動到指定磁道所須要的時間,通常在5ms內
  3. 半圈旋轉:找到指定磁道後還須要旋轉到達目標頁數據。
  4. 數據傳輸耗時: ,將數據從磁盤傳輸到數據庫緩衝區的時間,耗時相對較小 通常在1ms內。

其中尋道時間和旋轉時間稱爲服務時間。同數據庫緩衝區同樣,磁盤也有緩衝區,若數據存在於磁盤緩衝區,尋道時間和旋轉時間都可省略,IO時間將會下降在1ms左右。日誌

順序IO耗時估算

如下都是順序IO

  1. 全表掃描:通常是按順序讀取數據頁
  2. 全索引掃描: 按順序掃描存儲索引數據的頁。可是索引頁存儲的數據地址指針,指向的頁可能不連續,索引後對應的數據掃描是隨機IO
  3. 索引片掃描:同2
  4. 經過聚簇索引掃描錶行: 聚簇索引後直接指向數據,且聚簇索引的增加通常是連續的,聚簇索引所指向的地址頁也是連續的,是順序掃描。

通常DBMS會知道哪些索引和表頁須要被順序的讀取,且能識別出不在緩衝區的頁,而後發出多頁的一次IO請求。對於平均4K的表頁來講在40MB/s的讀取速度下,順序IO的耗時可能爲0.1ms.
且一般伴隨着預讀,在須要所需數據前將一部分數據讀取到緩衝區當中去。

增長索引的代價

響應耗時分析

前提:
假設在一個索引上添加一行須要耗時10ms當前狀況不考慮異步寫 那麼索引的新增須要找到對應的索引頁的插入位置,對於非聚簇索引這個位置一般不是最後一個索引頁末尾,尋找對於的索引頁是一個隨機IO過程,能夠認爲是估算值10ms
問題:

  1. 在一個事務中向一張有10條索引的表中插入1行數據。
  2. 在一個事務中向一張有10條索引的表中插入20行數據。

分析以上狀況下隨機IO次數:

  1. 10條索引包含9非聚簇索引和1聚簇索引。須要10次隨機讀。順序讀的第一次也是隨機讀,須要尋道時間 旋轉才能在後續開啓順序讀。
  2. 9個非聚簇索引須要9*20=180次隨機讀。聚簇第一次隨機後續都是順序讀。以供須要181次隨機讀。

磁盤負載分析

被修改的葉子頁最終都會落到磁盤上去,因爲數據庫的寫是異步的,因此寫不會影響事務時間,可是寫會增長磁盤的負載,若是一張表的插入較高的話,磁盤負載可能會變成限制索引數量的主要問題。

磁盤空間限制

若是一個表中有千萬行以上的數據,索引磁盤空間的成本可能會成爲一個限制因素,每一次數據的寫入都須要增長對應索引的空間。

相關文章
相關標籤/搜索