mysql加速搜索_巧用MySQL AHI加速神器,让你的InnoDB查询飞起来!
原標(biāo)題:巧用MySQL AHI加速神器,讓你的InnoDB查詢飛起來(lái)!
作者:張青林,騰訊云布道師、MySQL架構(gòu)師,隸屬騰訊TEG-基礎(chǔ)架構(gòu)部-CDB內(nèi)核開(kāi)發(fā)團(tuán)隊(duì),專注于MySQL內(nèi)核研發(fā)&相關(guān)架構(gòu)工作,有著服務(wù)多個(gè)10W級(jí)QPS客戶的數(shù)據(jù)庫(kù)優(yōu)化及穩(wěn)定性維護(hù)經(jīng)驗(yàn)。
騰訊云數(shù)據(jù)庫(kù)團(tuán)隊(duì):繼承騰訊數(shù)據(jù)庫(kù)團(tuán)隊(duì)十多年海量存儲(chǔ)的內(nèi)部數(shù)據(jù)庫(kù)運(yùn)營(yíng)和運(yùn)維經(jīng)驗(yàn),推出一系列高性能關(guān)系型、分布式、文檔型和緩存類數(shù)據(jù)庫(kù)產(chǎn)品,并提供高可用性、自動(dòng)化運(yùn)維和易維護(hù)的云數(shù)據(jù)庫(kù)綜合解決方案。
MySQL 定位用戶記錄的過(guò)程可以描述為:
打開(kāi)索引 -> 根據(jù)索引鍵值逐層查找 B+ 樹(shù) branch 結(jié)點(diǎn) -> 定位到葉子結(jié)點(diǎn),將 cursor 定位到滿足條件的 rec 上;
如果樹(shù)高為 N,則需要讀取索引樹(shù)上的 N 個(gè)結(jié)點(diǎn)并進(jìn)行比較,如果 buffer_pool 較小,則大量的操作都會(huì)在 pread 上,用戶響應(yīng)時(shí)間變長(zhǎng);
另外,MySQL 中 Server 層與 Engine 之間的是以 row 為單位進(jìn)行交互的,engine 將記錄返回給 server 層,server 層對(duì) engine 的行數(shù)據(jù)進(jìn)行相應(yīng)的計(jì)算,然后緩存或發(fā)送至客戶端,為了減少交互過(guò)程所需要的時(shí)間,MySQL 做了兩個(gè)優(yōu)化:
如果同一個(gè)查詢語(yǔ)句連續(xù)取出了 MYSQL_FETCH_CACHE_THRESHOLD(4) 條記錄,則會(huì)調(diào)用函數(shù) row_sel_enqueue_cache_row_for_mysql 將 MYSQL_FETCH_CACHE_SIZE(8) 記錄緩存至 prebuilt->fetch_cache 中,在隨后的 prebuilt->n_fetch_cached 次交互中,都會(huì)從prebuilt->fetch_cache 中直接取數(shù)據(jù)返回到 server 層,那么問(wèn)題來(lái)了,即使是用戶只需要 4 條數(shù)據(jù),Engine 層也會(huì)將 MYSQL_FETCH_CACHE_SIZE 條數(shù)據(jù)放入 fetch_cache 中,造成了不必要的緩存使用。另外,5.7 可以根據(jù)用戶的設(shè)置來(lái)調(diào)整緩存用戶記錄的條數(shù);
Engine 取出數(shù)據(jù)后,會(huì)將 cursor 的位置保存起來(lái),當(dāng)取下一條數(shù)據(jù)時(shí),會(huì)嘗試恢復(fù) cursor 的位置,成功則并繼續(xù)取下一條數(shù)據(jù),否則會(huì)重新定位 cursor 的位置,從而通過(guò)保存 cursor 位置的方法可以減少 server 層 & engine 層交互的時(shí)間;
Server 層 & engine 層交互的過(guò)程如下,由于 server & engine 的 row format 不一樣,那么 engine row format -> server row format 在讀場(chǎng)景下的開(kāi)銷也是比較大的。
1
AHI 功能作用
由以上的分析可以看到 MySQL 一次定位 cursor 的過(guò)程即是從根結(jié)點(diǎn)到葉子結(jié)點(diǎn)的路徑,時(shí)間復(fù)雜度為:height(index) + [CPU cost time],上述的兩個(gè)優(yōu)化過(guò)程無(wú)法省略定位 cursor 的中間結(jié)點(diǎn),因此需要引入一種可以從 search info 定位到葉子結(jié)點(diǎn)的方法,從而省略根結(jié)點(diǎn)到葉子結(jié)點(diǎn)的路徑上所消耗的時(shí)間,而這種方法即是自適應(yīng)索引(Adaptive hash index, AHI)。查詢語(yǔ)句使用 AHI 的時(shí)候有以下優(yōu)點(diǎn):
可以直接通過(guò)從查詢條件直接定位到葉子結(jié)點(diǎn),減少一次定位所需要的時(shí)間;
在 buffer pool 不足的情況下,可以只針對(duì)熱點(diǎn)數(shù)據(jù)頁(yè)建立緩存,從而避免數(shù)據(jù)頁(yè)頻繁的 LRU;
但是 AHI 并不總能提升性能,在多表Join & 模糊查詢 & 查詢條件經(jīng)常變化的情況下,此時(shí)系統(tǒng)監(jiān)控 AHI 使用的資源大于上述的好處時(shí),不僅不能發(fā)揮 AHI 的優(yōu)點(diǎn),還會(huì)為系統(tǒng)帶來(lái)額外的 CPU 消耗,此時(shí)需要將 AHI 關(guān)閉來(lái)避免不必要的系統(tǒng)資源浪費(fèi),關(guān)于 AHI 的適應(yīng)場(chǎng)景可以參考:https://docs.oracle.com/cd/E17952_01/mysql-5.6-en/innodb-adaptive-hash.html
2
AHI 內(nèi)存結(jié)構(gòu)
AHI 會(huì)監(jiān)控查詢語(yǔ)句中的條件并進(jìn)行分析(稍后會(huì)進(jìn)行詳細(xì)的介紹),當(dāng)滿足 AHI 緩存建立的條件后,會(huì)選擇索引的若干前綴索引列對(duì)熱點(diǎn)數(shù)據(jù)頁(yè)組建 hash page 以記錄 hash value -> page block 之間的對(duì)應(yīng)關(guān)系,本小節(jié)主要對(duì) AHI 的內(nèi)存結(jié)構(gòu) & 內(nèi)存來(lái)源進(jìn)行相應(yīng)的介紹,其內(nèi)存結(jié)構(gòu)如圖:
上圖是 AHI 的一個(gè)內(nèi)存結(jié)構(gòu)示意圖,AHI 主要使用以下兩種內(nèi)存:
系統(tǒng)初始化分配的 hash_table 的內(nèi)存,其中每一個(gè) hash_table 的數(shù)組大小為:(buf_pool_get_curr_size() / sizeof(void*) / 64),根據(jù)機(jī)器位數(shù)的不同,數(shù)組大小不同, 32位機(jī)器為 buffer_pool大小的 1/256, 64 位機(jī)器為 buffer_pool 大小的 1/512, 此部分內(nèi)存為系統(tǒng)內(nèi)存(mem_area_alloc->malloc),主要用于構(gòu)建 hash_table 結(jié)構(gòu);
當(dāng) AHI 對(duì)數(shù)據(jù)頁(yè)面構(gòu)造 AHI 緩存時(shí),此時(shí)使用 buffer_pool 的 free 鏈接中的內(nèi)存,即 buffer_pool 的內(nèi)存,所以在頁(yè)數(shù)據(jù)發(fā)生變化的時(shí)候,需要對(duì) AHI 緩存進(jìn)行相應(yīng)的維護(hù);
3
AHI 實(shí)現(xiàn)解析
AHI在查詢過(guò)程中的作用范圍
MySQL 中 Server & InnoDB 的交互中是以行為單位進(jìn)行交互的,InnoDB逐行取數(shù)據(jù)的過(guò)程可以分為以下 6 個(gè)步驟:
如果發(fā)現(xiàn)其它線程需要對(duì)btr_search_latch上鎖,則釋放 btr_search_latch,然后執(zhí)行 1; (5.6 & 5.7 在實(shí)現(xiàn)上不同)
嘗試從 row_prebuilt_t->fetch_cache 中取數(shù)據(jù)庫(kù)記錄,有則直接返回,如果沒(méi)有數(shù)據(jù)或者不可以使用 fetch cache, 則執(zhí)行2;
在滿足條件的情況下,使用 AHI 定位 cursor 位置并返回?cái)?shù)據(jù), 否則執(zhí)行 3;
根據(jù) direction 的值確認(rèn)是否可以從 row_prebuilt_t中恢復(fù) cursor 的位置,如果 direction = 0 或不可以從 row_prebuilt_t中恢復(fù) cursor 的位置, 則調(diào)用 btr_pcur_open_at_index_side 打開(kāi)索引,調(diào)用 btr_cur_search_to_nth_level,如果可以使用 AHI,則快速定位葉子結(jié)點(diǎn),否則遍歷 height(index) 個(gè)結(jié)點(diǎn)定位 cursor, 然后進(jìn)入 4;如果可以從 row_prebuilt_t 恢復(fù)則執(zhí)行 5;
根據(jù)查找的值在葉子結(jié)點(diǎn)中逐個(gè)匹配,查找滿足條件的記錄,返回?cái)?shù)據(jù),取下一條記錄時(shí)執(zhí)行 3,5;
移動(dòng) cursor 到下一條記錄并返回?cái)?shù)據(jù)。
AHI 則在第 [2, 3] 兩個(gè)步驟中影響著定位葉子結(jié)點(diǎn)的過(guò)程,根據(jù)查詢條件定位葉子節(jié)點(diǎn)的過(guò)程中發(fā)揮著 hash 的作用,AHI 的實(shí)現(xiàn)主要包括 AHI 初始化過(guò)程、構(gòu)建條件、使用過(guò)程、維護(hù)過(guò)程、系統(tǒng)監(jiān)控等部分,我們從源碼的實(shí)現(xiàn)的角度上分析上述過(guò)程。
AHI初始化過(guò)程
AHI 作為 buffer_pool 的一部分,是建立查詢條件與 REC 在內(nèi)存中位置的一個(gè) hash_table, 在系統(tǒng)啟動(dòng)的時(shí)候會(huì)隨著 buffer_pool 的初始化而自動(dòng)的建立相應(yīng)的內(nèi)存結(jié)構(gòu),其初始化過(guò)程為:
利用系統(tǒng)內(nèi)存 (malloc) 創(chuàng)建全局變量 btr_search_sys 及其鎖結(jié)構(gòu);
利用系統(tǒng)內(nèi)存 (malloc) 建立 hash_table 內(nèi)存結(jié)構(gòu),并初始化其成員變量,其中 hash_table 數(shù)組的大小取決于當(dāng)前 buffer_pool 的 size 與 系統(tǒng)的機(jī)器位數(shù),計(jì)算公式為:buf_pool_get_curr_size() / sizeof(void*) / 64,hash_table_t 的結(jié)構(gòu)如下所示:
說(shuō)明:
所有 buffer_pool instances 共享一個(gè) AHI, 而不是每一個(gè) buffer_pool instance 一個(gè) AHI;
5.7.8 之前 AHI 只有一個(gè)全局的鎖結(jié)構(gòu) btr_search_latch,當(dāng)壓力比較大的時(shí)候會(huì)出現(xiàn)性能瓶頸,5.7.8 對(duì) AHI 進(jìn)行了拆鎖處理,詳情可以參考函數(shù): btr_get_search_table() & btr_search_sys_create();
AHI 的 btr_search_latch (bug#62018) & index lock 是MySQL中兩個(gè)比較大的鎖(詳情可以參考:https://www.percona.com/blog/2010/02/25/index-lock-and-adaptive-search-next-two-biggest-innodb-problems/)。5.7 通過(guò)對(duì) AHI 鎖拆分 (5.7 commit id: ab17ab91) 以及引入不同的索引鎖協(xié)議 (WL#6326) 解決了這兩個(gè)問(wèn)題。
AHI構(gòu)建條件
AHI 是建立在 search info & REC 內(nèi)存地址之間的映射信息,在系統(tǒng)接受訪問(wèn)之前并沒(méi)有足夠的信息來(lái)建立 AHI 的映射信息,所以需要搜集 SQL 語(yǔ)句在執(zhí)行過(guò)程中的 search_info & block info 信息并判斷是否可以為數(shù)據(jù)頁(yè)建立 AHI 緩存,其中:
search info 對(duì)應(yīng) btr_search_t, 用于記錄 index 中的 n_fields (前綴索引列數(shù)) & n_bytes(last column bytes) 信息,這些被用于計(jì)算 fold 值;
block info 用于記錄計(jì)算 fold 的值所需要的 fields & bytes 之外,還記錄了在此情況下使用 AHI 在此數(shù)據(jù)頁(yè)上潛在成功的次數(shù);
我們簡(jiǎn)單地對(duì)AHI統(tǒng)計(jì)信息的幾個(gè)方面進(jìn)行描述。
觸發(fā) AHI 索引統(tǒng)計(jì)的條件
SQL 語(yǔ)句在定位 cursor 的過(guò)程中會(huì)執(zhí)行 btr_cur_search_to_nth_level 函數(shù),當(dāng)打開(kāi) AHI 的時(shí)候,在btr_cur_search_to_nth_level 返回之前會(huì)調(diào)用 btr_search_info_update 來(lái)更新相應(yīng)的統(tǒng)計(jì)信息,如果當(dāng)前的索引的 serch_info->hash_analysis < BTR_SEARCH_HASH_ANALYSIS (17),則對(duì) search info & block info 不進(jìn)行統(tǒng)計(jì),否則則會(huì)調(diào)用 btr_search_info_update_slow 更新 search info & block info 信息,實(shí)現(xiàn)如下:
AHI中索引查詢信息(index->search_info)的更新與自適應(yīng)的過(guò)程
背景知識(shí):
btr_cur_search_to_nth_level 中在定位 cursor 的過(guò)程中會(huì)在樹(shù)的每一層調(diào)用 page_cur_search_with_match 來(lái)確定下一個(gè) branch 結(jié)點(diǎn)或葉子結(jié)點(diǎn),page_cur_search_with_match 函數(shù)會(huì)將查詢過(guò)程中比較的前綴索引列數(shù) & 最后一列匹配的字節(jié)數(shù)記錄至 {cursor->up_match, cursor->up_bytes, cursor->low_bytes, cursor->low_match},目的是為了保存與 search tuple 在比較過(guò)程時(shí)的最小比較單元,詳細(xì)的計(jì)算過(guò)程可以參考 page_cur_search_with_match 的實(shí)現(xiàn)代碼。
首先判斷當(dāng)前 index 是否為 insert buffer tree,如果是 insert buffer,則不進(jìn)行 AHI 等相關(guān)的操作;
其次,如果當(dāng)前索引的 info->n_hash_potential = 0,則會(huì)按照推薦算法從 {cursor->up_match, cursor->up_bytes, cursor->low_bytes, cursor->low_match} 推薦出前綴索引列數(shù) & 最后一列的字節(jié)數(shù)用于計(jì)算 AHI 中存儲(chǔ)的鍵 {ha_node_t->fold} 的值。
當(dāng) info->n_hash_potential != 0 時(shí),則會(huì)判斷當(dāng)前查詢匹配模式 & index->search_info 中保存的匹配模式是否發(fā)生變化,如果沒(méi)有發(fā)生變化,則會(huì)增加此模式下潛在利用 AHI 成功的次數(shù) (info->n_hash_potential),否則需要重新推薦前綴索引列等相關(guān)信息,并清空 info->n_hash_potential 的值(info->n_hash_potential = 0),AHI 就是利用這種方法來(lái)實(shí)現(xiàn)自適應(yīng)的,所以在打開(kāi) AHI 的系統(tǒng)中不建議經(jīng)常變換查詢條件,前綴索引等信息的計(jì)算過(guò)程如下:
由以上算法可以看出,選擇{info->n_fields, info->n_bytes, info->left_side}的依據(jù)則是在不超過(guò) unique index 列數(shù)的前提下,使其計(jì)算代價(jià)最小,而 index->info->left_side 的值則會(huì)決定存儲(chǔ)同一數(shù)據(jù)頁(yè)上相同前綴索引的最左記錄還是最右記錄。
數(shù)據(jù)頁(yè)block信息的更新
數(shù)據(jù)頁(yè) block info 的更新主要包括數(shù)據(jù)頁(yè)上的索引匹配模式、在已有索引匹配模式下成功的次數(shù)以及是否為該數(shù)據(jù)頁(yè)建立 AHI 緩存信息的判斷,其主要過(guò)程如下:
將 index->info->last_hash_succ 設(shè)置為 FALSE,此時(shí)其它線程無(wú)法使用該索引上 AHI 功能;
如果 index->search_info 的匹配格式 & 該數(shù)據(jù)頁(yè)上保存的匹配模式相同時(shí),則增加此 block 使用 AHI 成功的次數(shù) block->n_hash_helps, 如果已經(jīng)為該數(shù)據(jù)頁(yè)建立 AHI 緩存,則設(shè)置 index->info->last_hash_succ = TRUE;
如果 index->search_info 的匹配格式 & 該數(shù)據(jù)頁(yè)上保存的匹配模式不相同,則設(shè)置 block->n_hash_helps=1 且使用 index->search_info 對(duì) block 上的索引匹配信息進(jìn)行重新設(shè)置,詳細(xì)過(guò)程可參考 btr_search_update_block_hash_info;
判斷是否需要為數(shù)據(jù)頁(yè)建立 AHI 緩存,在數(shù)據(jù)頁(yè) block 上使用 AHI 成功的次數(shù)大于此數(shù)據(jù)頁(yè)上用戶記錄的 1/16 且當(dāng)前前綴索引的條件下使用 AHI 成功的次數(shù)大于 100 時(shí), 如果此數(shù)據(jù)頁(yè)使用 AHI 潛在成功的次數(shù)大于 2 倍該數(shù)據(jù)頁(yè)上的用戶記錄或者當(dāng)前推薦的前綴索引信息發(fā)生了變化的時(shí),則需要為數(shù)據(jù)頁(yè)構(gòu)造 AHI 緩存信息,詳情可參考以下代碼;
AHI構(gòu)建過(guò)程(收集&判斷&建立)
AHI 的構(gòu)建過(guò)程指的是根據(jù) index->search_info 構(gòu)建查詢條件 & 數(shù)據(jù)頁(yè)的 hash 關(guān)系,其主要過(guò)程為:
1、收集 hash 信息。遍歷該數(shù)據(jù)頁(yè)上的所有用戶記錄,建立由前綴索引信息&物理記錄之間的映射關(guān)系的數(shù)組{folds, recs},其中index->info->left_side用來(lái)判斷在前綴索引列相同情況下如何保存物理頁(yè)記錄,從代碼中可以得知:當(dāng)left_side為TRUE時(shí)前綴索引列相同的記錄只保存最左記錄,當(dāng)left_side為FALSE時(shí)前綴索引列相同的記錄只保存最右記錄,代碼實(shí)現(xiàn)如下:
2、如果之前該數(shù)據(jù)頁(yè)已經(jīng)存在 AHI 緩存信息但前綴索引信息與當(dāng)前的信息不一致,則釋放之前緩存的 AHI 信息,如果釋放超過(guò)了一個(gè) page size,則將釋放的數(shù)據(jù)頁(yè)退還給 buffer_pool->free 鏈表;
3、調(diào)用 btr_search_check_free_space_in_heap 來(lái)確保 AHI 有足夠的內(nèi)存生成映射信息 ha_node_t {fold, data, next},該內(nèi)存從 buffer_pool->free 鏈表獲得,詳情參考:buf_block_alloc(), fold 的值的計(jì)算可參考函數(shù):rec_fold();
4、由于操作過(guò)程中釋放了 btr_search_latch,需要再次檢查 block 上的AHI信息是否發(fā)生了變化,如果發(fā)生變化則退出函數(shù);
5、調(diào)用 ha_insert_for_fold 方法將之前收集的信息生成 ha_node_t, 并將其存放到 btr_search_sys->hash_table 的數(shù)組中,其中存放后的結(jié)構(gòu)可以參考圖 AHI memory structure;
for (i = 0; i < n_cached; i++) {
ha_insert_for_fold(table, folds[i], block, recs[i]);
}
AHI使用條件及定位葉子結(jié)點(diǎn)過(guò)程
在“AHI 在查詢過(guò)程中的作用范圍”一節(jié)中我們?cè)敿?xì)的介紹了 MySQL 中 Server 層 & engine 層中的交互方式以及 AHI 在整個(gè)過(guò)程中的位置 & 作用,下面著要看一下在 步驟 2、3 中 AHI 是如何工作的。
步驟 2 中,是使用 AHI 的一種 shortcut 查詢方式,只有在滿足很苛刻的條件后才能使用 AHI 的 shortcut 查詢方式,這些苛刻條件包括:
當(dāng)前索引是 cluster index;
當(dāng)前查詢是 unique search;
當(dāng)前查詢不包含 blob 類型的大字段;
記錄長(zhǎng)度不能大于 page_size/8;
不是使用 memcache 接口協(xié)議的查詢;
事物開(kāi)啟且隔離級(jí)別大于 READ UNCOMMITTED;
簡(jiǎn)單 select 查詢而非在 function & procedure;
在滿足以上條件后才能使用 AHI 的 shortcut 查詢方式定位葉子結(jié)點(diǎn),5.7 中滿足條件后的操作可以簡(jiǎn)單的描述為:
rw_lock_s_lock(btr_get_search_latch(index));
...
row_sel_try_search_shortcut_for_mysql()
...
rw_lock_s_lock(btr_get_search_latch(index));
步驟 3 中使用 AHI 快速定位葉子結(jié)點(diǎn)同樣需要滿足一些條件,具體可以參考代碼:btr_cur_search_to_nth_level(),在此不再累述,我們著重分析一下使用 AHI 定位葉子節(jié)點(diǎn)的過(guò)程。
1、對(duì) index 所在的 hash_table 上鎖,使用查詢條件中的 tuple 信息計(jì)算出鍵值 fold;
rw_lock_s_lock(btr_search_get_latch(index));
fold = dtuple_fold(tuple, cursor->n_fields, cursor->n_bytes, index_id);
2、在 hash_table 上進(jìn)行查找 key = fold 的 ha_node_t;
3、釋放鎖資源并根據(jù)返回的記錄定位葉子結(jié)點(diǎn);
block = buf_block_align(rec);
rw_lock_s_unlock(btr_search_get_latch(index));
btr_cur_position(index, (rec_t*) rec, block, cursor);
4、定位到葉子結(jié)點(diǎn)后的過(guò)程和不使用 AHI 之后的過(guò)程類似,直接返回記錄并記錄 cursor 位置。
AHI維護(hù)&監(jiān)控
MySQL 5.7 中有兩個(gè) AHI 相關(guān)的參數(shù),分別為:
innodb_adaptive_hash_index, innodb_adaptive_hash_index_parts,其中 innodb_adaptive_hash_index 為動(dòng)態(tài)調(diào)整的參數(shù),用以控制是否打開(kāi) AHI 功能;innodb_adaptive_hash_index_parts 是只讀參數(shù),在實(shí)例運(yùn)行期間是不能修改,用于調(diào)整 AHI 分區(qū)的個(gè)數(shù)(5.7.8 引入),減少鎖沖突,詳細(xì)介紹可以參考官方說(shuō)明:innodb_adaptive_hash_index及innodb_adaptive_hash_index,本節(jié)主要介紹操作 AHI 的相關(guān)命令以及命令的內(nèi)部實(shí)現(xiàn)過(guò)程。
1)打開(kāi)AHI操作&內(nèi)部實(shí)現(xiàn)
set global innodb_adaptive_hash_index=ON,此命令只是對(duì)全局變量進(jìn)行設(shè)置,代碼實(shí)現(xiàn)如下:
2)關(guān)閉AHI操作&內(nèi)部實(shí)現(xiàn)
set global innodb_adaptive_hash_index= OFF,此命令用于關(guān)閉 AHI 功能,具體實(shí)現(xiàn)可參考 btr_search_disable(), 關(guān)閉流程說(shuō)明:
設(shè)置 btr_search_enabled = FALSE,關(guān)閉 AHI 功能;
將數(shù)據(jù)字典中所有緩存的表對(duì)象的 ref_count 設(shè)置為0,只有 btr_search_info_get_ref_count(info, index) = 0 的情況下才能清除數(shù)據(jù)字典中的緩存對(duì)象,詳情見(jiàn) dict_table_can_be_evicted();
將所有數(shù)據(jù)頁(yè)中的統(tǒng)計(jì)信息置空,具體實(shí)現(xiàn)可參考 buf_pool_clear_hash_index();
釋放 AHI 所使用的 buffer_pool 的內(nèi)存,btr_search_disable 具體實(shí)現(xiàn)如下:
3) AHI緩存信息的維護(hù)
AHI 維護(hù)的是 search info & REC 在物理內(nèi)存地址的 hash 關(guān)系,當(dāng)物理記錄的位置或者所在 block 的地址發(fā)生變化時(shí),AHI 也需要對(duì)其進(jìn)行相應(yīng)的維護(hù),如新記錄的的插入,表記錄的的刪除,數(shù)據(jù)頁(yè)的分裂,drop table & alter table,LRU 換頁(yè)等都需要對(duì) AHI 進(jìn)行相應(yīng)的維護(hù),詳情可參考函數(shù) btr_search_update_hash_ref() & btr_search_drop_page_hash_index() & buf_LRU_drop_page_hash_for_tablespace()的實(shí)現(xiàn);
4) AHI信息的監(jiān)控
AHI 默認(rèn)情況下只對(duì) adaptive_hash_searches (使用 AHI 方式查詢的次數(shù)) & adaptive_hash_searches_btree (使用 bree 查詢的次數(shù),需要遍歷 branch 結(jié)點(diǎn)) 進(jìn)行監(jiān)控,更詳細(xì)的監(jiān)控需要進(jìn)行額外的設(shè)置,詳細(xì)設(shè)置方法可參考 innodb_monitor_enable &module_adaptive_hash,打開(kāi) AHI 的監(jiān)控方法、使用監(jiān)控、重置監(jiān)控的方法如下:
值得一提的是只有執(zhí)行 set global innodbmonitor_reset_all='adaptive_hash%' & set global innodb_monitor_disable='adaptive_hash%' 才對(duì)狀態(tài)進(jìn)行重置,如果發(fā)現(xiàn) adaptive_hash_searches << adaptive_hash_searches_btree 的時(shí)候,則應(yīng)該關(guān)閉 AHI 以減少不必要的系統(tǒng)消耗。
相關(guān)專題:
精選專題(官網(wǎng):dbaplus.cn)
◆近期熱文 ◆
◆MVP專欄 ◆
丨丨丨丨
責(zé)任編輯:
總結(jié)
以上是生活随笔為你收集整理的mysql加速搜索_巧用MySQL AHI加速神器,让你的InnoDB查询飞起来!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 全网最全-网络模型低比特量化
- 下一篇: 【COCOS2DX-游戏开发之二四】 q