你真的懂資料庫的索引嗎(下篇)

2021-10-07 12:13:37 字數 1862 閱讀 6129

mysql對索引的選擇

給字串加索引

select id from t where a=1;對於上述這條select語句,首先從b+樹的樹根開始,按層搜尋到葉子節點,然後再根據二分法來定位記錄。

只能說兩者的查詢效率差別不大,innodb的資料是按照頁為單位來讀寫的,當讀到一條記錄的時候,並不是把這個資料從磁碟讀出來,而是以頁為單位,讀到記憶體中,對於在記憶體中多檢索幾條記錄,消耗很低。但是有一種特殊情況,就是這個檢索的key剛好位於資料頁的最後乙個數,所以讀取下乙個記錄的時候,需要把另乙個資料頁載入進記憶體。

這裡需要先引入乙個概念:change buffer。當更新乙個資料頁的時候,如果資料在記憶體中就會直接更新,如果資料不在記憶體中的話,在不影響一致性的前提下,innodb會把這些更新操作快取在change buffer中,這樣就不需要從磁碟中讀入資料頁。當這個資料頁被讀進記憶體的時候,這個時候就會執行change buffer中與這個頁有關的操作,通過這種方式來保證這個資料邏輯的準確性。

change buffer的資料和資料頁資料合併的過程叫做merge,系統的後台執行緒會定期把資料merge到磁碟中的資料頁,在資料庫關閉的時候,也會進行merge操作。

了解完這個change buffer的概念,接下來看看兩種索引更新的過程

資料頁在記憶體中的情況

資料頁不在記憶體中的情況

普通索引和唯一索引在查詢上區別不大,主要區別在於更新操作。普通索引具有chang buffer,而唯一索引沒有。對於寫多讀少的場景,change buffer能夠極大的提高效率。所以考慮業務場景,一般來說選擇普通索引的可能性比較大

關於change buffer 一開始是寫記憶體但是機器突然故障重啟,這時候的情況分析:

change buffer有一部分資料在記憶體中,有一部分資料在ibdata中,做清除的時候,會把change buffer裡面的資料持久化到ibdata中。

redo log日誌記錄了資料頁的修改和change buffer中寫入的訊息。

如果這個時候故障,分情況來分析:

1、change buffer裡面的資料已經持久化到磁碟中,這個時候就不用管了

2、沒持久化到磁碟中,這個時候就分為以下幾種情況

一張資料庫表可能有多個索引,但是你寫sql語句的時候,並沒有主動指定使用哪個索引,說明這個索引是mysql來確定的。

選擇索引是優化器的工作,找到最優執行方案。並用最小代價去執行語句。優化器的判斷標準由臨時表、是否排序,掃瞄行數等因素決定的。

這裡講講mysql是怎麼判斷掃瞄行數的

在還沒執行語句之前,mysql會根據統計資訊來估計記錄數,這個統計資訊其實就是索引的區分度

那何為索引的區分度呢?

乙個索引上不同值個數被稱之為基數,這個基數越大,索引的區分度就越好。

那這裡又有乙個問題了,就是mysql怎麼得到索引的基數呢?

這裡採用的是取樣統計的方式,innodb預設選擇n個資料頁,統計頁面上的不同值,得到乙個平均值,將這個平均值乘索引的頁面數,就可以得到其基數。資料表會不斷更新,索引統計資訊也不是一層不變,當變更的資料行達到一定量的時候,就會重新觸發一次索引統計。因為採用的是取樣統計,所以這個資料是不準確的,只是乙個大概的值。

當然這個基數只是優化器的乙個考慮因素,普通索引的話會有乙個回表操作,這個效能消耗優化器也是會考慮在內的。當然優化器的選擇不一定是正確的,但是大部分情況還是能夠做出正確選擇的

直接建立完整索引,這樣比較占用空間

建立字首索引,節省空間,但是覆蓋索引將失效

倒序儲存,再建立索引,可以繞開正序字串區分度不夠的情況

建立hash欄位索引。

注:3、4點都不支援範圍掃瞄

你真的懂資料庫的索引嗎(上篇)

你真的了解列式資料庫嗎

傳統的關係型資料庫是行式資料庫,因為關聯式資料庫是按照行來儲存資料的,而列式資料庫就是按照列來儲存資料的資料庫。行式資料庫的主要優勢有以下兩點。第一點是業務同時讀取多列的時候,效率比較高,因為這些列都是按行儲存在一起的,一次磁碟操作就能夠把一行資料中的列都讀到記憶體中,第二點,是能夠一次性完成對一行...

你真的懂遞迴 或者 寫的好遞迴嗎

一 什麼是遞迴?1.遞迴是一種非常高效 簡潔的編碼技巧,一種應用非常廣泛的演算法,比如dfs深度優先搜尋 前中後序二叉樹遍歷等都是使用遞迴。2.方法或函式呼叫自身的方式稱為遞迴呼叫,呼叫稱為遞,返回稱為歸。3.基本上,所有的遞迴問題都可以用遞推公式來表示,比如 f n f n 1 1 f n f n...

老生常談!資料庫如何儲存時間?你真的知道嗎?

我們平時開發中不可避免的就是要儲存時間,比如我們要記錄操作表中這條記錄的時間 記錄轉賬的交易時間 記錄出發時間等等。你會發現這個時間這個東西與我們開發的聯絡還是非常緊密的,用的好與不好會給我們的業務甚至功能帶來很大的影響。所以,我們有必要重新出發,好好認識一下這個東西。我記得我在大學的時候就這樣幹過...