【StoneDB Class】入門第四課:StoneDB 的體系結(jié)構(gòu)


本次課程為大家介紹 StoneDB 的體系結(jié)構(gòu)。StoneDB 的體系結(jié)構(gòu)分為內(nèi)存管理和文件管理,其中內(nèi)存管理由內(nèi)存堆和線程池組成,文件管理由分布在磁盤的一系列物理文件組成。

內(nèi)存
Main Heap
主堆內(nèi)存,對數(shù)據(jù)進行更新和查詢會分配主堆內(nèi)存用于緩存數(shù)據(jù),執(zhí)行批量插入會分配 insert buffer,由參數(shù) tianmu_ini_servermainheapsize 控制主堆內(nèi)存大小,單位為 MB,默認(rèn)值為操作系統(tǒng)物理內(nèi)存的1/2。StoneDB 啟動時可以在 tianmu.log 看到 Main Heap 分配的大小,主堆內(nèi)存的大小建議保持默認(rèn)值。
System Heap
系統(tǒng)堆內(nèi)存,當(dāng)主堆內(nèi)存使用達到最大限制時,使用該內(nèi)存。由于主堆內(nèi)存在默認(rèn)情況下已經(jīng)分配了操作系統(tǒng)物理內(nèi)存的1/2,因此正常情況下是不會出現(xiàn)使用系統(tǒng)堆內(nèi)存的。如果出現(xiàn)了使用系統(tǒng)堆內(nèi)存的情況,大概率是由于 SQL 消耗大量內(nèi)存或者系統(tǒng)發(fā)生了內(nèi)存泄漏。
Large Temporary Heap
臨時堆內(nèi)存,執(zhí)行 group by、union 以及子查詢時會分配該內(nèi)存,用于緩存臨時結(jié)果集。臨時堆內(nèi)存大小由參數(shù) tianmu_mm_largetempratio 和 tianmu_ini_servermainheapsize 的乘積決定,前者參數(shù)值是個百分比,默認(rèn)是0,表示不使用臨時堆內(nèi)存,用的是主堆內(nèi)存。StoneDB 啟動時可以在 tianmu.log 中看到 Large Temporary Heap 分配的大小,由于主堆內(nèi)存已分配操作系統(tǒng)物理內(nèi)存的1/2,因此臨時堆內(nèi)存的大小建議保持默認(rèn)值。
線程池
delay_insert_thread_pool
創(chuàng)建和分配 delay insert thread,線程的作用是將 insert buffer 中的數(shù)據(jù)刷新到磁盤,由參數(shù) tianmu_bg_load_threads 控制線程池中線程數(shù)量,默認(rèn)為0,表示線程池中的線程數(shù)量等于 CPU 核數(shù)的1/2。StoneDB 啟動時可以在 tianmu.log 中看到分配的線程數(shù)。
load_thread_pool
創(chuàng)建和分配 load thread,線程的作用是將插入、修改、導(dǎo)入的數(shù)據(jù)刷新到磁盤,由參數(shù) tianmu_load_threads 控制線程池中線程數(shù)量,默認(rèn)為0,表示線程池中的線程數(shù)量等于 CPU 核數(shù)。StoneDB 啟動時可以在 tianmu.log 中看到分配的線程數(shù)。
query_thread_pool
創(chuàng)建和分配 query thread,線程的作用是用于查詢,由參數(shù) tianmu_query_threads 控制線程池中線程數(shù)量,默認(rèn)為0,表示線程池中的線程數(shù)量等于 CPU 核數(shù)。StoneDB 啟動時可以在 tianmu.log 看到分配的線程數(shù)。
物理存儲結(jié)構(gòu)
StoneDB 的物理存儲結(jié)構(gòu)指的是存儲在文件系統(tǒng)上的文件,包括參數(shù)文件、數(shù)據(jù)文件、日志文件。
參數(shù)文件
參數(shù)文件記錄了各個文件所在的位置以及實例啟動時的初始化參數(shù)等,參數(shù)文件的默認(rèn)位置在?basedir 下,文件名默認(rèn)為 my.cnf,StoneDB 的參數(shù)名以“tianmu”為前綴。參數(shù)文件中的參數(shù)根據(jù)是否可以在實例中直接修改,分為以下兩類參數(shù):
1)動態(tài)參數(shù):可以在實例中直接修改,并且可基于當(dāng)前變量或者全局變量進行修改,但實例重啟后會失效,如?tianmu_force_hashjoin。
2)靜態(tài)參數(shù):不能直接在實例中修改,只能修改參數(shù)文件,并且實例重啟后才生效,如?tianmu_insert_buffer_size。
數(shù)據(jù)文件
在 StoneDB 創(chuàng)建一張表,文件系統(tǒng)上會自動創(chuàng)建以表名命名的兩個文件,一個是表結(jié)構(gòu)定義文件,命名為?xxx.frm,另一個是數(shù)據(jù)文件,命名為?xxx.tianmu。表結(jié)構(gòu)定義文件包含表結(jié)構(gòu)的描述,無論哪種存儲引擎,只要創(chuàng)建一張表,就會創(chuàng)建表結(jié)構(gòu)定義文件,我們重點關(guān)注的是數(shù)據(jù)文件。
數(shù)據(jù)文件下面分為1個目錄和3個文件,結(jié)構(gòu)如下所示:
TABLE_DESC
返回值是 TianmuTB,表示表使用的存儲引擎是 Tianmu。
V.xxx
表的版本號,創(chuàng)建一個新表后,版本號默認(rèn)是 V.0000000000000000,對表做 DML 后,版本號就會遞增。如果執(zhí)行 DML ,但沒有匹配的行,版本號保持不變。如果執(zhí)行 DDL ,版本號不會立即改變。
VERSION
V.xxx?的軟連接。
columns
StoneDB 是個列式存儲數(shù)據(jù)庫,創(chuàng)建的表有多少個列,在文件系統(tǒng)上就有多少個從 0 開始遞增的編號。即0表示表的第一個字段,1表示表的第二個字段,以此類推。上文中 columns 目錄下有編號 0~7 的子目錄,說明這張表有 8 個列,每個編號的子目錄下面又分了 2 個目錄和 3 個文件,結(jié)構(gòu)如下所示:
DATA
存儲的是經(jīng)過壓縮后的 Data Pack,一個 Data Pack 存儲了65,536行數(shù)據(jù)。如果一個 Data Pack 是可疑的,那么線程就會從 DATA 文件讀取這個 Data Pack 到內(nèi)存,知識網(wǎng)格對這個可疑的 Data Pack 進行解壓縮,然后讀取解壓出來符合查詢條件的數(shù)據(jù)行。
DATA 文件大小與 information_schema.columns 中 column_comment 返回值近似。
DN
存儲的是 Data Pack Node,記錄了 Data Pack 的基本元數(shù)據(jù),包含 Data Pack 中列的最大值、最小值、平均值、總和、總記錄數(shù)、null值的數(shù)量。Data Pack Node 與 Data Pack 是一一對應(yīng)的關(guān)系。
META
存儲的是 Data Pack 的壓縮格式以及其列的數(shù)據(jù)類型等。
V
和上文提到的 VERSION 相同,是個版本號。
filters
filters 目錄下是知識節(jié)點的基本類型,正常情況下是個空目錄,數(shù)據(jù)被加載時會自動創(chuàng)建。
hist:數(shù)據(jù)類型為整型、日期型、浮點型的列的統(tǒng)計值以直方圖的形式存在。將一個數(shù)據(jù)包的最小值到最大值之間分為1,024段,每段占用一個 bit,如果數(shù)據(jù)包中的實際值處于段中的范圍,則標(biāo)記為1,否則標(biāo)記為0。
cmap:數(shù)據(jù)類型為字符串的列的字符映射表。統(tǒng)計當(dāng)前數(shù)據(jù)包內(nèi) 1~64 長度中 ASCII 字符是否存在。如果存在,則標(biāo)記為1,否則標(biāo)記為0。字符檢索時,按照字符順序依次對比字符標(biāo)識值即可知道該數(shù)據(jù)包是否包含匹配數(shù)據(jù)。
日志文件
StoneDB 的日志文件有三種,分別是 tianmu.log、trace.log、query.log,其中 tianmu.log 是 StoneDB 的引擎日志,記錄了 StoneDB 運行過程中的詳細(xì)信息,以上三種日志默認(rèn)都在 basedir/log 下。
tianmu.log
記錄了 StoneDB 在啟動和關(guān)閉過程的詳細(xì)信息,以及 StoneDB 在運行過程中發(fā)生的較為嚴(yán)重的錯誤信息、警告信息、狀態(tài)信息,發(fā)生錯誤時的調(diào)用堆棧等。
StoneDB 在啟動時,會記錄分配的線程數(shù)、主堆內(nèi)存大小、insert buffer 大小等。如果在 StoneDB 創(chuàng)建不支持的對象會有錯誤提示,創(chuàng)建不支持的數(shù)據(jù)類型會有告警提示,并且會顯示調(diào)用的堆棧。tianmu.log 也會記錄在 StoneDB 創(chuàng)建和刪除的對象,并且記錄過去一分鐘內(nèi)發(fā)生的查詢次數(shù),更新、插入、插入失敗行數(shù),以及自上一次 StoneDB 啟動以來,查詢總次數(shù),更新、插入、插入失敗總行數(shù)。
trace.log
trace.log 記錄了 StoneDB 的 debug 版本在進行調(diào)試時的日志。如果想知道表關(guān)聯(lián)使用的是哪種表連接方式可開啟參數(shù) tianmu_control_trace,然后觀察 trace.log 的輸出。
如果是 StoneDB 的 release 版本,即便開啟了參數(shù) tianmu_control_trace,trace.log 也沒有任何輸出,因為參數(shù) tianmu_control_trace 只對 StoneDB 的 debug 版本有效。
query.log
query.log 記錄了在 StoneDB 發(fā)起的任何查詢語句,由參數(shù) tianmu_ini_controlquerylog 控制,默認(rèn)為1,表示在 StoneDB 發(fā)起的任何查詢語句都會被記錄。由于生產(chǎn)環(huán)境的查詢語句很多,如果開啟參數(shù) tianmu_ini_controlquerylog,那么 query.log 會很大,且可篩選性較差。在運維中常用的方法是開啟慢查詢?nèi)罩荆槍?zhí)行時間超過指定閥值的 SQL 進行記錄,因此生產(chǎn)環(huán)境建議關(guān)閉這個參數(shù),query.log 不記錄任何的查詢語句。
以上是本次課程的全部內(nèi)容,下節(jié)課程將為大家介紹關(guān)于 StoneDB 的表連接方式,請各位繼續(xù)關(guān)注。如果您對 StoneDB 感興趣,歡迎前往 StoneDB 代碼倉庫了解更多,期待您的加入。
END