1.索引的本質
mysql 官方對索引的定義為:索引(index)是幫助mysql高效獲取資料的資料結構。從中可以得出索引的本質:索引說白了就是一種資料結構;
資料庫查詢是資料的重要功能之一,最基本的查詢演算法是:順序查詢(linear search),顯然在資料量很大的時候,效率是很低的。優化的查詢演算法如:二分查詢法,二叉樹查詢等;雖然查詢的效率提高了。但是各自的檢索的資料都有要求:二分查詢要求檢索的資料必須是有序的,而二叉樹查詢只能應用在二叉查詢樹上;而資料本身的組織結構是不可能完全滿足各種資料的結構的;所以,在資料之外,資料庫系統還維護著滿足特定的查詢演算法的資料結構。這些資料結構以某種方式引用(指向)資料,這樣就可以在這些資料結構上實現高階的查詢演算法。這種資料結構就是索引。
在了解為什麼要使用 b-tree這種外存資料結構前,先要了解一些硬體的知識:
2.外儲存器-磁碟:
我們可以清楚知識,計算機一般有兩種儲存的方式:記憶體和外存;
記憶體:讀寫速度非常快,但是容量很小,而且造價非常貴,在不通電的情況下會資料會丟失,不能長期儲存資料
外存:磁碟是相對常見的外儲存裝置,它是以訪問時間變化不大為特徵的。可以直接訪問任何字元組,且容量大、速度較其它外存裝置更快。
2.1 磁碟的構造
磁碟跟我們***那些其實是乙個樣的。。。盤面上有很多稱為磁軌的圓圈,資料就記錄在上面。磁碟可以是單片的,也可以使若干碟片組成的盤組,每一盤片上有兩個面。如下圖6片盤組為例,除去最頂端和最底端的外側面不儲存資料之外,一共有10個面可以用來儲存資訊。
當磁碟驅動器執行讀/寫功能時。碟片裝在乙個主軸上,並繞主軸高速旋轉,當磁軌在讀/寫頭(又叫磁頭) 下通過時,就可以進行資料的讀 / 寫了。
磁碟讀取資料是以盤塊(block)為基本單位的。位於同一盤塊中的所有資料都能被一次性全部讀取出來。而磁碟io代價主要花費在查詢時間ts上。因此我們應該盡量將相關資訊存放在同一盤塊,同一磁軌中。或者至少放在同一柱面或相鄰柱面上,以求在讀/寫資訊時儘量減少磁頭來找時間ts。
3.b-tree
b-tree 又叫平衡多路查詢樹。一顆m階的b-tree(m叉樹)的特性如下:
樹的每個結點至多有m個孩子;
除根結點和葉子結點外,其它每個結點至少有有ceil(m / 2)個孩子;
若根結點不是葉子結點,則至少有2個孩子(特殊情況:沒有孩子的根結點,即根結點為葉子結點,整棵樹只有乙個根節點);
所有葉子結點都出現在同一層,葉子結點不包含任何關鍵字資訊(可以看做是外部結點或查詢失敗的結點,實際上這些結點不存在,指向這些結點的指標都為null);
在b-tree中按key檢索資料的演算法非常直觀:首先從根節點進行二分查詢,如果找到則返回對應節點的data,否則對相應區間的指標指向的節點遞迴進行查詢,直到找到節點或找到null指標,前者查詢成功,後者查詢失敗。
4.b+tree
b+-tree:是應檔案系統所需而產生的一種b-tree的變形樹。
一棵m階的b+-tree和m階的b-tree的差異在於:
1.有n棵子樹的結點中含有n個關鍵字; (b-tree是n棵子樹有n-1個關鍵字)
2.所有的葉子結點中包含了全部關鍵字的資訊,及指向含有這些關鍵字記錄的指標,且葉子結點本身依關鍵字的大小自小而大的順序鏈結。 (b-tree的葉子節點並沒有包括全部需要查詢的資訊)
3.所有的非終端結點可以看成是索引部分,結點中僅含有其子樹根結點中最大(或最小)關鍵字。 (b-tree的非終節點也包含需要查詢的有效資訊)
mysql索引使用的就是b+tree,而不是b-tree;那這又是為什麼呢?
1) b+-tree的磁碟讀寫代價更低
b+-tree的內部結點並沒有指向關鍵字具體資訊的指標。因此其內部結點相對b-tree更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入記憶體中的需要查詢的關鍵字也就越多。相對來說io讀寫次數也就降低了。
舉個例子,假設磁碟中的乙個盤塊容納16bytes,而乙個關鍵字2bytes,乙個關鍵字具體資訊指標2bytes。一棵9階b-tree(乙個結點最多8個關鍵字)的內部結點需要2個盤快。而b+-tree內部結點只需要1個盤快。當需要把內部結點讀入記憶體中的時候,b-tree就比b+-tree多一次盤塊查詢時間(在磁碟中就是碟片旋轉的時間)。
2) b+-tree的查詢效率更加穩定
由於非終結點並不是最終指向檔案內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查詢必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每乙個資料的查詢效率相當。
其實mysql對資料儲存,就是資料的持久化;而資料的持久化就是將資料寫到硬碟;
若想提高mysql的讀寫有效的操作的就是減少磁碟的i/o操作;想要減少i/o操作,最好的方法就是遵循:區域性性原理與磁碟預讀
5.區域性性原理與磁碟預讀
由於儲存介質的特性,磁碟本身訪問就比主存慢很多,再加上機械運動耗費,磁碟的訪問速度往往是主存的幾百分分之一,因此為了提高效率,要儘量減少磁碟i/o。為了達到這個目的,磁碟往往不是嚴格按需讀取,而是每次都會預讀,即使只需要乙個位元組,磁碟也會從這個位置開始,順序向後讀取一定長度的資料放入記憶體。這樣做的理論依據是電腦科學中著名的區域性性原理:
當乙個資料被用到時,其附近的資料也通常會馬上被使用。
程式執行期間所需要的資料通常比較集中。
由於磁碟順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間),因此對於具有區域性性的程式來說,預讀可以提高i/o效率。
預讀的長度一般為頁(page)的整倍數。頁是計算機管理儲存器的邏輯塊,硬體及作業系統往往將主存和磁碟儲存區分割為連續的大小相等的塊,每個儲存塊稱為一頁(在許多作業系統中,頁得大小通常為4k),主存和磁碟以頁為單位交換資料。當程式要讀取的資料不在主存中時,會觸發乙個缺頁異常,此時系統會向磁碟發出讀盤訊號,磁碟會找到資料的起始位置並向後連續讀取一頁或幾頁載入記憶體中,然後異常返回,程式繼續執行。
計算機的主存和輔存
計算機的主存是指下邊兩個 1.ram random access memory 隨機訪問儲存器,即我們電腦的記憶體條 2.rom read only memory 唯讀儲存器,這種儲存器用途比較少,一般就是電腦中存放boot的地方,我們啟動電腦的時候,電腦先讀rom中的內容,比如我們的bios系統,...
mysql存類 mysql 儲存型別
char 和 varchar 型別 char 型別用於定長字串,並且必須在圓括號內用乙個大小修飾符來定義。這個大小修飾符的範圍從 0 255。比指定長度大的值將被截短,而比指定長度小的值將會用空格作填補。char 型別可以使用 binary 修飾符。當用於比較運算時,這個修飾符使 char 以二進位...
mysql怎麼實現行級索 Mysql
mysql innodb的特點 innodb如何實現事務 redo和undo,兩次提交 mysql預設的事務隔離級別 innodb如何儲存檔案 如何最高效的遍歷乙個上億的表 朋友關係如何分表 使用者數上千萬 冗餘 支援事務 原子性 atomicity 一致性 consistency 隔離性 isol...