最近今天寫了IoTDB的三篇相關文章,完成了安裝部署和客戶端連線:
TsFile 是 IoTDB 的底層資料檔案,一種專門為時間序列資料設計的列式檔案格式。IoTDB TsFile資料讀寫主要是下面兩個結構:
- IoTDB 提供了一個TSRecord工具,TSRecord記錄了一個裝置在一個時間戳下的若干測點資訊。在c# 客戶端裡被抽象成了Row Record
- IoTDB 提供了一個Tablet工具,Tablet記錄了一個裝置的多個測點的資訊,按照一種表格的形式表示,這些測點具有相同的時間戳序列,因此可以應用在測點具有相同時間戳序列(每個時間戳下各個測點都具有值)的裝置中。
IoTDB C# SDK 叫做 Apache-IoTDB-Client-CSharp,Github:https://github.com/eedalong/Apache-IoTDB-Client-CSharp ,Nuget 包有兩個:
Apache.IoTDB和 Apache.IoTDB.Data。 其中 Apache.IoTDB.Data 是對ADO .NET支援,以.NET 讀取資料庫的方式方便不同使用習慣的使用者, C#客戶端也及時更新支援最新的Apache IoTDB的特性,如對齊序列插入、SchemaTemplate操縱介面的 支援、支援插入空值的Tablet結構等。
最近剛剛釋出了對IoTDB 1.0版本的支援的1.0.0.1預覽版已經發布,歡迎各位試用並提issue~: https://www.nuget.org/packages/Apache.IoTDB/1.0.0.1-alpha
使用示例
// 引數定義
string host = "localhost";
int port = 6667;
int pool_size = 2;
// 初始化session
var session_pool = new SessionPool(host, port, pool_size);
// 開啟session
await session_pool.Open(false);
// 建立時間序列
await session_pool.CreateTimeSeries("root.test_group.test_device.ts1", TSDataType.TEXT, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
await session_pool.CreateTimeSeries("root.test_group.test_device.ts2", TSDataType.BOOLEAN, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
await session_pool.CreateTimeSeries("root.test_group.test_device.ts3", TSDataType.INT32, TSEncoding.PLAIN, Compressor.UNCOMPRESSED);
// 插入record
var measures = new List<string>{"ts1", "ts2", "ts3"};
var values = new List<object> { "test_text", true, (int)123 };
var timestamp = 1;
var rowRecord = new RowRecord(timestamp, values, measures);
await session_pool.InsertRecordAsync("root.test_group.test_device", rowRecord);
// 插入Tablet
var timestamp_lst = new List<long>{ timestamp + 1 };
var value_lst = new List<object> {new() {"iotdb", true, (int) 12}};
var tablet = new Tablet("root.test_group.test_device", measures, value_lst, timestamp_ls);
await session_pool.InsertTabletAsync(tablet);
// 關閉Session
await session_pool.Close();
詳細介面資訊可以參考介面文件
連線池
C#客戶端暴露的所有介面均為非同步介面。使用C#客戶端從首先建立一個SessionPool開始,建立SessionPool時需要指定伺服器的IP 、Port 以及
SessionPool的大小,SessionPool的大小代表本地與伺服器建立的連線的數目。為了實現併發客戶端請求,客戶端提供了針對原生介面的連線池(SessionPool
),由於SessionPool
本身為Session
的超集,當SessionPool
的pool_size
引數設定為1時,退化為原來的Session
客戶端 使用ConcurrentQueue
資料結構封裝了一個客戶端佇列,以維護與服務端的多個連線,當呼叫Open()
介面時,會在該佇列中建立指定個數的客戶端,同時透過System.Threading.Monitor
類實現對佇列的同步訪問。
當請求發生時,會嘗試從連線池中尋找一個空閒的客戶端連線,如果沒有空閒連線,那麼程式將需要等待直到有空閒連線
當一個連線被用完後,他會自動返回池中等待下次被使用
在使用連線池後,客戶端的併發效能提升明顯,這篇文件展示了使用執行緒池比起單執行緒所帶來的效能提升
ByteBuffer
在傳入RPC介面引數時,需要對Record和Tablet兩種資料結構進行序列化,我們主要透過封裝的ByteBuffer類實現
在封裝位元組序列的基礎上,我們進行了記憶體預申請與記憶體倍增的最佳化,減少了序列化過程中記憶體的申請和釋放,在一個擁有20000行的Tablet上進行序列化測試時,速度比起原生的陣列動態增長具有35倍的效能加速,詳見以下兩篇文件:
在庫裡 有一個 IoTDB C#客⼾端效能分析報告:https://github.com/eedalong/Apache-IoTDB-Client-CSharp/blob/main/docs/time_profile_zh.pdf ,建議大家看一看,這裡只說結論:
- 在插⼊與該⽤⼾類似的結構化較強、沒有空值、規整、每⾏的column固定的的資料時,建議使⽤insert_tablet接⼝,經過改善後的insert_tablet接⼝具備較好的效能,能滿⾜該⽤⼾的需求
- 資料量較⼤,但資料整體不規整或者有空值,每⾏資料的column數不定時建議使⽤insert_records接⼝,該接⼝對record資料的插⼊速度較為可觀
- 資料量⼩,需要對原有資料做出⼀定的修正 時,使⽤insert_record接⼝
參考文章:
- Apache IoTDB C#客戶端介紹: https://github.com/eedalong/Apache-IoTDB-Client-CSharp/blob/main/docs/Apache%20IoTDB%20C%23%E5%AE%A2%E6%88%B7%E7%AB%AF%E4%BB%8B%E7%BB%8D%20(6).pdf
- IoTDB C#客⼾端效能分析報告:https://github.com/eedalong/Apache-IoTDB-Client-CSharp/blob/main/docs/time_profile_zh.pdf
- API 介面: https://github.com/eedalong/Apache-IoTDB-Client-CSharp/blob/main/docs/API.md