mysql資料庫樹 MySQL資料庫索引之B 樹

2021-10-18 11:28:15 字數 3716 閱讀 9860

一、b+樹是什麼

b+ 樹是一種樹型資料結構,通常用於資料庫和作業系統的檔案系統中。b+ 樹的特點是能夠保持資料穩定有序,其插入與修改操作擁有較穩定的對數時間複雜度。b+ 樹元素自底向上插入,這與二叉樹恰好相反。

b+ 樹的創造者rudolf bayer沒有解釋b代表什麼。最常見的觀點是b代表平衡(balanced),因為所有的葉子節點在樹中都在相同的級別上。b也可能代表bayer,或者是波音(boeing),因為他曾經工作於波音科學研究實驗室

1)b+樹的節點

在 b+ 樹中的節點通常被表示為一組有序的元素和子指標。如果此b+樹的序數(order)是m ,則除了根之外的每個節點都包含最少 [m/2] 個元素最多 [m-1] 個元素,對於任意的節點有最多 m 個子指標。對於所有內部節點,子指標的數目總是比元素的數目多乙個.

2)b+樹相應的操作

1.查詢

2.插入

3.刪除

3)b+樹的特點

1.每個節點中子節點的個數不能超過 m,也不能小於 m/2;

2.根節點的子節點個數可以不超過 m/2,這是乙個例外;

3.m 叉樹只儲存索引,並不真正儲存資料,這個有點兒類似跳表;

4.通過鍊錶將葉子節點串聯在一起,這樣可以方便按區間查詢;

5.一般情況,根節點會被儲存在記憶體中,其他節點儲存在磁碟中

4)在這裡說下b 樹、b- 樹

b- 樹就是 b 樹,英文翻譯都是 b-tree,這裡的「-」並不是相對 b+ 樹中的「+」,而只是乙個連線符。

而 b 樹實際上是低階版的 b+ 樹,或者說 b+ 樹是 b 樹的改進版。b 樹跟 b+ 樹的不同點主要集中在這幾個地方:

b+ 樹中的節點不儲存資料,只是索引,而 b 樹中的節點儲存資料;

b 樹中的葉子節點並不需要鍊錶來串聯。

也就是說,b 樹只是乙個每個節點的子節點個數不能小於 m/2 的 m 叉樹

b-tree:

b+tree:

二、mysql資料庫索引為啥使用b+樹作為底層資料結構

1)明確資料庫索引是解決什麼問題的

這裡舉最常用的兩個功能性需求:

1.根據某個值查詢資料,比如 select * from user where id=1234;

2.根據區間值來查詢某些資料,比如 select * from user where id > 1234 and id < 2345;

然後是非功能性需求比如效能方面的:

主要考察時間和空間兩方面,也就是執行效率和儲存空間。

在執行效率方面,我們希望通過索引,查詢資料的效率盡可能的高;在儲存空間方面,我們希望索引不要消耗太多的記憶體空間。

2)明確了待解決的問題,然後就是用已知的資料結構解決問題

我們已知的支援快速查詢、插入等操作的動態資料結構有:雜湊表、平衡二叉查詢樹、跳表、b+樹

1.雜湊表 (不滿足)

雜湊表的查詢效能很好,時間複雜度是 o(1)。但是,雜湊表不能支援按照區間快速查詢資料

2.平衡二叉查詢樹(不滿足)

平衡二叉查詢樹查詢的效能也很高,時間複雜度是 o(logn)。而且,對樹進行中序遍歷,我們還可以得到乙個從小到大有序的資料序列,但這仍然不足以支援按照區間快速查詢資料

3.跳表(滿足)

跳表是在鍊錶之上加上多層索引構成的。它支援快速地插入、查詢、刪除資料,對應的時間複雜度是 o(logn)。並且,跳表也支援按照區間快速地查詢資料。我們只需要定位到區間起點值對應在鍊錶中的結點,然後從這個結點開始,順序遍歷鍊錶,直到區間終點對應的結點為止,這期間遍歷得到的資料就是滿足區間值的資料。

4.b+樹 (滿足)

b+樹這種資料結構跟跳表非常相似,所以適合做資料庫索引。不過,它是通過二叉查詢樹演化過來的,而非跳表。

3)確定使用b+樹後,那麼如何解決索引占用太多記憶體的問題呢?

因為作為資料庫索引,儲存的資料可能非常的大,比如給一億個資料構建索引,那索引中會包含大約 1 億個節點,每個節點假設占用 16 個位元組,那就需要大約 1gb 的記憶體空間。給一張表建立索引,我們需要 1gb 的記憶體空間。如果我們要給 10 張表建立索引,那對記憶體的需求是無法滿足的。

那麼我們就需要借助空間換時間的思路,把索引儲存在硬碟中,而非記憶體中。我們都知道,硬碟是乙個非常慢速的儲存裝置。通常記憶體的訪問速度是納秒級別的,而磁碟訪問的速度是毫秒級別的。讀取同樣大小的資料,從磁碟中讀取花費的時間,是從記憶體中讀取所花費時間的上萬倍,甚至幾十萬倍。

將索引儲存在硬碟中後,儘管減少了記憶體消耗,但是在資料查詢的過程中,需要讀取磁碟中的索引,因此資料查詢效率就相應降低很多。對於b+樹來說,每個節點的讀取(或者訪問),都對應一次磁碟 io 操作。樹的高度就等於每次查詢資料時磁碟 io 操作的次數。我們優化的重點就是儘量減少磁碟 io 操作,也就是,盡量降低樹的高度。

4)為了提高b+樹索引的效率,那麼如何降低樹的高度?

對於b+樹來說,其實可以看做是 m 叉樹,那麼樹的高度就取決於 m 的大小。比如給 16 個資料構建二叉樹索引,樹的高度是 4,查詢乙個資料,就需要 4 個磁碟 io 操作(如果根節點儲存在記憶體中,其他結點儲存在磁碟中),如果對 16 個資料構建五叉樹索引,那高度只有 2,查詢乙個資料,對應只需要 2 次磁碟操作。如果 m 叉樹中的 m 是 100,那對一億個資料構建索引,樹的高度也只是 3,最多只要 3 次磁碟 io 就能獲取到資料。磁碟 io 變少了,查詢資料的效率也就提高了。

m越大,樹的高度就越小,那麼m是不是越大越好呢?不是,不管是記憶體中的資料,還是磁碟中的資料,作業系統都是按頁(一頁大小通常是 4kb,這個值可以通過 getconfig page_size 命令檢視)來讀取的,一次會讀一頁的資料。如果要讀取的資料量超過一頁的大小,就會觸發多次 io 操作。所以,我們在選擇 m 大小的時候,要盡量讓每個節點的大小等於乙個頁的大小。讀取乙個節點,只需要一次磁碟 io 操作。

5)索引的使用也會導致寫入資料效率的下降

儘管索引可以提高資料庫的查詢效率,但是,作為一名開發工程師,你應該也知道,索引有利也有弊,它也會讓寫入資料的效率下降

/*** 這是 b+ 樹非葉子節點的定義。

* 假設 keywords=[3, 5, 8, 10]

* 4 個鍵值將資料分為 5 個區間:(-inf,3), [3,5), [5,8), [8,10), [10,inf)

* 5 個區間分別對應:children[0]...children[4]

* m 值是事先計算得到的,計算的依據是讓所有資訊的大小正好等於頁的大小:

* page_size = (m-1)*4[keywordss 大小]+m*8[children 大小]*/

public classbplustreenode /*** 這是 b+ 樹中葉子節點的定義。

* b+ 樹中的葉子節點跟內部結點是不一樣的,

* 葉子節點儲存的是值,而非區間。

* 這個定義裡,每個葉子節點儲存 3 個資料行的鍵值及位址資訊。

* k 值是事先計算得到的,計算的依據是讓所有資訊的大小正好等於頁的大小:

* page_size = k*4[keyw.. 大小]+k*8[dataad.. 大小]+8[prev 大小]+8[next 大小]*/

public classbplustreeleafnode {public static int k = 3;public int keywords = new int[k]; //資料的鍵值

public long dataaddress = new long[k]; //資料位址

public bplustreeleafnode prev; //這個結點在鍊錶中的前驅結點

public bplustreeleafnode next; //這個結點在鍊錶中的後繼結點

MySQL資料庫基礎 MySQL資料庫與資料表操作

資料表操作 3.修改表名 4.更改表的自增的值 5.修改表引擎 6.刪除表 資料表的操作 資料庫操作 1.資料庫的建立 鏈結mysql資料庫後,進入demo後可以運算元據 1.建立庫 create database if not exists demo default charset utf8 1....

Mysql資料庫B 樹

一般來說,索引檔案占用空間比較大,需要儲存在磁碟上。索引查詢需要通過磁碟i o操作才能進行,而我們知道,磁碟i o比記憶體讀取要高幾個數量級,所以如何減少磁碟i o次數,是索引資料結構選擇的首要參考條件。計算機區域性性原理認為 當乙個資料被用到時,其附近的資料也通常會馬上被使用。因此為了減少磁碟i ...

mysql資料庫載入太慢 使用MySQL資料庫很慢

對於2000資料庫,您應該調整table cache設定.您肯定在此快取中有很多快取未命中.嘗試使用mysqltunner和 或tunning primer.sh獲取有關設定潛在問題的其他資訊.現在drupal使資料庫工作量很大,請檢查一下drupal的安裝,您可能會生成很多 太多 的請求.關於in...