本篇內(nèi)容介紹了“Apache TDB性能優(yōu)化的知識點有哪些”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!
豐南網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站建設(shè)等網(wǎng)站項目制作,到程序開發(fā),運營維護。創(chuàng)新互聯(lián)從2013年創(chuàng)立到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
關(guān)于存儲組
現(xiàn)在每個存儲組是一個相對獨立的引擎,而且讀寫鎖是存儲組級別的。因此把存儲組從1改到10,讀寫基本能增速8倍。單個 IoTDB 實例推薦設(shè)置 CPU 核數(shù)個存儲組。存儲組越多,并行度就越高。我們之后打算把鎖粒度下放到設(shè)備層。
設(shè)備
設(shè)備這個概念沒有在 SQL 語句里顯示的定義出來,而是在服務(wù)器端處理時候默認將倒數(shù)第二層設(shè)置為設(shè)備,導(dǎo)致大家容易忽略這個概念。先說一下設(shè)備影響什么。
(1)區(qū)分順序數(shù)據(jù) 和 亂序數(shù)據(jù)是以設(shè)備為粒度的。舉個例子,假如一個設(shè)備在內(nèi)存里寫了時間戳 1-10 的數(shù)據(jù)(不論寫哪些測點,時間戳都會算到這個設(shè)備頭上),落盤了,再寫時間戳<=10 的數(shù)據(jù),這些數(shù)據(jù)就會被當做亂序數(shù)據(jù)緩存并落盤。
(2)設(shè)備粒度的時間范圍索引。對于每個 TsFile 文件,會構(gòu)造設(shè)備粒度的索引在內(nèi)存里,假如所有設(shè)備都活躍,N 個 TsFile,D 個設(shè)備,就有 N*D 條索引。百萬級設(shè)備的索引內(nèi)存會吃不消。這個東西我們會在一兩個版本內(nèi)改掉。
再說一下怎么設(shè)計建模來控制設(shè)備數(shù)。對于實際應(yīng)用設(shè)備和傳感器層次比較簡單的情況比較好說,設(shè)備下直接是傳感器層,一般不會建錯。對于設(shè)備下有多層結(jié)構(gòu)的就要注意了。
比如我一個設(shè)備下有10個傳感器(s1,s2,...,s10),每個傳感器采集10個時間序列的數(shù)據(jù)(f1,f2,...f10)。這時候很容易建成 root.xxx.device.s1.f1 這種。當你建成這種時候,你以為的 device 就不再是你以為的 device 了,實際的device 變成了 root.xxx.device.s1 。 實際 device 數(shù)量就是你以為的 10 倍了。
怎么辦嘞,如果設(shè)備下的子設(shè)備不多,這樣建模也沒啥問題,只要你心里清楚系統(tǒng)中實際有多少個設(shè)備就行,這樣溝通不會出現(xiàn)偏差,便于以后排查問題。
如果子設(shè)備非常多,可以把設(shè)備后的那幾層壓成一層,比如 root.xxx.device.s1_f1 。由于我們是以 . 作為分隔符的,這樣 s1_f1 就變成 1 層了。 實際的設(shè)備還是 root.xxx.device。
Measurement 定義
Measurement 也就是最后一層的測點。假如一個測點是 INT32 或者 INT64 類型的,而且大部分時間這個數(shù)據(jù)的值都一樣,沒什么變化,這時候用 RLE 編碼就很好??梢源蟠蠊?jié)省磁盤空間,當然刷盤速度也會變快。壓縮方式開著 SNAPPY 就挺好。
Tag & Attribute
0.10.0 引入的這兩個概念,容易分不清這兩個有啥區(qū)別。 雖然都是 key-value 類型的屬性。但是 Tag 是可以反向查詢時間序列的元數(shù)據(jù)的,假如有個 tag 的 key 是 owner,就可以用 show timeseries where owner=Thanos 查滅霸擁有的時間序列。Tag 常駐內(nèi)存,有Tag到時間序列的索引。
Attribute 就是普通屬性了,比如有個屬性是 description="this is my series"。這些屬性只能是給定時間序列的路徑順帶展示一下,輔助人查看的。
因此,要根據(jù)實際需求進行區(qū)分,那些需要做反向查詢的屬性,就建成 tag,其他的就搞成 attribute 就行了。
讀寫優(yōu)化
讀和寫關(guān)系密切,數(shù)據(jù)的寫入和參數(shù)配置會影響查詢性能。
寫入接口
以 0.10 為例,先同類比較,insertRecords 接口肯定比 insertRecord 接口要快,這個類似 JDBC 的 executeBatch 和 execute 的區(qū)別,節(jié)省了網(wǎng)絡(luò)通信次數(shù)。同理,insertTablets 比 insertTablet 要快,createMultiTimeseries 也比 createTimeseries 要快。
進一步,insertRecords 方法我們提供了兩種,一種是傳 Object 的 value,一種是傳 String 的 value。如果客戶端能獲取 value 的類型,建議用 Object 的,會比 String 的快 25% 左右。
跨類比較的話,如果不考慮客戶端做格式轉(zhuǎn)化的耗時,insertTablet 比 insertRecords 要快很多,可能 8 倍以上,節(jié)省了很多對象封裝的耗時,batch size 1000左右就可以。
insertTablet 這個接口默認是沒排序的,如果你能保證一個 Tablet 數(shù)據(jù)的時間戳是非遞減的,那就可以多加一個 sorted 為 true 的參數(shù)。就節(jié)省了客戶端的排序。
在統(tǒng)計耗時的時候,還需要注意客戶端做格式轉(zhuǎn)化的耗時,可以把接口參數(shù)構(gòu)造的時間和執(zhí)行的時間分開統(tǒng)計。
查詢接口
查詢接口比較簡單,Session 默認的 hasNext 和 next 會返回 RowRecord 結(jié)構(gòu),這個結(jié)構(gòu)不一定大家都需要,可以用 SessionDataSet 的 iterator 得到一個迭代器,然后通過類似 JDBC 的接口去得到原始數(shù)據(jù),避免很多沒用的對象生成。
順序?qū)懭?/strong>
對于時序數(shù)據(jù)庫,時序是一個很重要的概念,最好不要亂來。IoTDB 支持數(shù)據(jù)的亂序?qū)懭?,但是亂序數(shù)據(jù)會影響查詢性能,主要是對于聚合查詢,原理是亂序數(shù)據(jù)會讓預(yù)計算的統(tǒng)計信息失效,把聚合查詢降維打擊到讀原始數(shù)據(jù)。
正常情況下,有個幾倍的亂序都沒問題,但是如果往一個時間段寫入了過多(幾萬倍)的亂序數(shù)據(jù),查詢時候有可能爆內(nèi)存。舉個例子,內(nèi)存緩沖區(qū)寫了時間戳1-10的數(shù)據(jù)落盤了,然后又寫了 9999 遍 1-10 的緩沖區(qū),這樣磁盤上就有 1 萬個時間戳是 1-10 的數(shù)據(jù)塊。查詢時候需要將 1萬 個數(shù)據(jù)塊都讀出來進行合并,內(nèi)存占用就比較大了。
面對這種場景,我們會后臺做數(shù)據(jù)整理來處理亂序(在0.9引入的merge,但是0.9版本有bug,0.10修掉了,但是先默認關(guān)掉了,會在0.11重新開放merge),但是如果能在客戶端避免亂序,就盡量寫入的時候避免掉。一個設(shè)備就按遞增的順序?qū)懭搿?/p>
如果前邊接了 kafka,最好注意一下,把設(shè)備 id 作為分區(qū)粒度,這樣一個設(shè)備的數(shù)據(jù)都會發(fā)送到一個分區(qū)里,消費的時候同一個分區(qū)也能保證順序。
內(nèi)存緩沖區(qū)
先介紹一下每個序列在內(nèi)存里能緩存多少個點的怎么算的,用 memtable 大小除以序列數(shù),再除以每個點的大小,比如long類型就是 16字節(jié)(8字節(jié)時間戳,8字節(jié)值),float是12字節(jié)。
memtable 的大小可以從日志里看到,搜 reaches,大概日志就是 the memtable size xxx reaches the threshold。如果配置文件里的 enable_parameter_adapter 沒有改為 false,這個 memtable 大小就不固定,隨著注冊的序列數(shù)量調(diào)整的。
內(nèi)存緩沖區(qū)在一定范圍內(nèi)盡可能大有利于讀寫。平均每個序列能緩沖100萬點以下是比較好的。但是不建議太大,查詢時候會臨時排序,如果內(nèi)存中數(shù)據(jù)點過多,比如千萬級,查詢時候內(nèi)存排序會占個十幾秒。
為了避免這個問題,0.10.0 里加了個參數(shù),avg_series_point_number_threshold ,默認是 10000,也就是內(nèi)存緩沖區(qū)中每個序列最多緩存這么多點就會刷盤,這個默認參數(shù)沒給好,可以改成50萬或者100萬。
memtable_size_threshold 這個參數(shù)越大,寫入速度快,一般在幾百M到一兩G左右。不要設(shè)置的過小,比如幾M,會嚴重影響寫入速度。在設(shè)置這個參數(shù)時候需要注意不要超內(nèi)存限制,調(diào)這個參數(shù)之前需要保證 enable_parameter_adapter 改為 false。
多數(shù)據(jù)目錄
數(shù)據(jù)庫的瓶頸在磁盤IO,簡單的提升磁盤IO能力的就是配置多盤。IoTDB 的數(shù)據(jù)目錄可以在 data_dirs 參數(shù)配置,用逗號分隔多個目錄??梢悦繅K盤一個目錄。在寫數(shù)據(jù)的時候會到這幾個盤里找最空閑的寫。
客戶端優(yōu)化
剛才說了存儲組級別的鎖,對于同一個存儲組的N個寫線程,這N個寫線程都會搶一把鎖,一個存儲組對應(yīng)不超過50個客戶端比較好,寫線程過多會導(dǎo)致過多的鎖競爭。
線程池 SessionPool 的容量,一般搞個服務(wù)器 CPU 核數(shù)就可以了,不要過多。
客戶端的內(nèi)存,數(shù)據(jù)的生產(chǎn)和消費速率也可以監(jiān)控起來,避免提交的任務(wù)積壓過多,如果客戶端內(nèi)存滿了,會出現(xiàn)一個現(xiàn)象:客戶端發(fā)送請求到服務(wù)器,服務(wù)器執(zhí)行和返回很快,但是客戶端接收結(jié)果會很慢。
容易爆內(nèi)存的點
select * from root 這個語句在序列過多時候最好不要做,這個操作會把整個庫當做一張表,一下查出來所有列的一批數(shù)據(jù),容易爆內(nèi)存,我們會在0.11版本加個檢查,及時拒絕。
show timeseries 在 0.10 及以前的版本會把系統(tǒng)所有序列在內(nèi)存里拷貝一遍傳給客戶端,如果序列過多,最好指定前綴做個過濾?;蛘?show child paths 一層一層往下查。
時間序列過多(億級),元數(shù)據(jù)可能爆內(nèi)存,可以按照一條時間序列 200字節(jié)估計一下,大概1千萬序列會占2G元數(shù)據(jù)(就是那個元數(shù)據(jù)樹)。
“Apache TDB性能優(yōu)化的知識點有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!