アリクラウドInfluxDB®ベースTSIインデックスデータのクエリ処理

簡単な紹介

時系列データベース技術は、最も急速に成長しているデータベースの種類の一つです。業界で最も人気のあるデータベースのタイミングInfluxDBとして、その展開は非常に簡単で便利な操作であり、読み、高性能の時系列データを書き込み、アプリケーションの監視をサポートし、モノのインターネット(IOT)のフィールドは、アプリケーションの広い範囲を持っています。

アリ雲InfluxDB®は、オープンソース版InfluxDB最適化されたバージョンに基づいており、データの内部組織は、オープンソースのバージョンと一致しているインデックスデータを持つ2つの部分にまとめることができます。データクエリ用のユーザーInfluxql文、InfluxDBはインデックスInfluxDBで検索する時系列データに対応し、タグKVやその他の情報をこの文を解析し、構文木トラバーサルを通じて、ASTの構文木を生成するキーメタデータの測定を見つける照会しますデータポイントを得るために、(TSM)ファイル、ユーザに返さ。インデックスが達成され、状況のダウンタイムが発生した場合2、1は、メモリの使用によって制限転置インデックスメモリ(inmem)に基づいている、あなたは文書をスキャンしてメモリに再建され、すべてのTSM、回復時間を解決するが必要とされています長い;他が反転インデックスファイル(TSI)、小さなメモリフットプリントに基づいており、レベルのタイムラインの何百万あるいは数千をサポートすることができ、ダウンタイムの回復はほとんど効果があります。

本稿では、ファイルインデックス転置インデックス(TSI)、ユーザデータクエリ一度深い導入、内部InfluxDBにおける処理内容の種類に基づいて説明します。

プロセスの概要

クエリの入り口

内部InfluxDBがサービスhttpdサービス外部要求を処理する責任を負っているサービスの数を、登録され、通常、読み取りおよび書き込み要求は、ここでのhttpd / handler.go /サービスに到達します。select文の場合は、呼び出しがserveQueryです。

準備クエリ

更新カウンタ、パラメータ解析、ASTの解析ツリーの生成、証明4つの側面を含む準備照会、。

1は、統計カウント

統計カウント、h.stats.QueryRequests問い合わせカウンタを1増加させます。第二に、延期の定義は、統計のために現在のクエリの終了時に、時間がかかります。

defer func(start time.Time) {
    atomic.AddInt64(&h.stats.QueryRequestDuration, time.Since(start).Nanoseconds())
}(time.Now())

図2は、パラメータ解析

フォームInfluxdbは、出力形式として、データベース・アクセス、ストレージ戦略の詳細を決定するために重要な構成パラメータの数によって提出クエリを解決する必要があります。

パラメーター名 効果
Q 質問
NODE_ID Cluster EditionはノードIDは、スタンドアローンバージョンが無効です
時代 クエリ出力フォーマット、選択値はエポック= [H、M、S、MS、U、NS]
デシベル データベースを照会するには
RP ストレージ戦略を照会するために、
params 追加のパラメータ
チャンク バッチの代わりに単一の点応答のフロー・リターン・ポイントを制御します。trueに設定すると、InfluxDBまたは各シリーズは、ポイント(デフォルト10000)応答パケットをCHUNK_SIZEます。
CHUNK_SIZE パケット・サイズの対応点
非同期 同期クエリが返すかどうか

図3は、ASTツリーを生成

クエリフォームから抽出するために、InfluxDBは、従来のリレーショナル・データベースと同様ASTツリー内で生成することができる独自のセットInfluxql分析の枠組みを有しています。コードのInfluxql巨大な一部であるため、クエリ・ロジック・コアとはほとんど、このテキストは起動しません。

4、認証

、セキュリティ上の理由から、ユーザーが認証設定InfluxDB上にあってもよいです。唯一のユーザー権限と関連するデータベースにアクセスするための正しいパスワードを照合した後、対応します。

クエリを実行

準備が完了した後、最終的にexecuteSelectStatement機能コーディネーター/ statement_executor.goを実行しますが、この機能は、クエリの処理です。HTTPD / handler.go serveQueryのサービス/からexecuteSelectStatementのコーディネーター/ statement_executor.goに、関数呼び出しの層を介し。コードを読むために読者の便宜のために、次の図は、コールスタックを示す(遭遇した関数呼び出しは、インターフェース部を行けば、次の図は、インタフェースの構造の実際の機能に置き換えられています)。


テスト


executeSelectStatement関数内、いくつかの重要なアクションがあります:
(1)、TSIによって内部アクセスTSM部を作成するプロセスをイテレータcreateIteratorsを作成し、データ内容(「問い合わせの詳細:イテレータとTSI、TSM」の詳細な分析)を復号するために、
( 2)エミッタ反復子は、カーソルのいずれかからデータを読み取るためにスキャン()関数を循環させることによってカーソル機能エミッタベースのコールを作成しました。

以下は、データエミッタを読み出す際に遭遇することができるいくつかの状況である:
一連の複数の場合(A)、一般的に一連のデータを取り、次いで第2のデータを取得する最初のものである...... ;後、ように第2のデータを取り戻すと、一連のを取る
クエリはデータセットCHUNKSIZE(NOクエリパラメータ、デフォルト10,000)に達し返す場合、(B)への最初の前進復帰をこのバッチを実行する結果を返し、
クエリは、この重合操作をカウントするために類似している場合(C)、それはまた、CURから集計結果データ、減速操作関連イテレータに入れ重合作業を返すことができる;
(Dあなたがスキャンされたデータと、それはCURを強制的に読み取るために継続する必要性をデコードしている場合)、再び基礎となるTSMファイルをデコードください。するまでは、読み取ったデータを完了する必要があります。


TEST2

クエリが返します

場合クエリの端部は、結果が順次同期ケース管から除去されます。そして、プロトコル処理チャンクリターンプロトコルは、最終的にユーザーに返さ。

お問い合わせの詳細:イテレータとTSI、TSM

CreateIterator

我们提到执行select的主函数executeSelectStatement一个关键操作是创建迭代器(或者说是游标)cursor,这一思想与传统关系型数据库执行计划树的执行过程有相似之处。cursor的创建依赖于查询准备工作中由InfluxQL解析生成的AST树(SelectStatement)。创建过程也类似于传统关系型数据库,分为Prepare、Select两部,其中Prepare过程还可以细分为Compile与Compile之后的Prepare;Select则是基于Prepare后的SelectStatement来构建迭代器。

Prepare过程

Prepare过程先执行了Compile,Compile主要进行以下操作:
1、预处理,主要是解析、校验和记录当前查询状态的全局属性,例如解析查询的时间范围、校验查询条件合法性、校验聚合条件的合法性等等。
2、fields预处理,例如查询带time字段的会自动替换为timstamp。
3、重写distinct查询条件。
4、重写正则表达式查询条件。

Compile之后的Prepare主要进行以下操作:
1、如果查询带聚合,且配置了max-select-buckets限制,且查询时间范围下界未指定时,需要根据限制重写查询时间范围下界。
2、如果配置了额外的查询间隔配置,修正查询时间范围上下界。
3、根据时间上下界获取需要查询的shards map(LocalShardMapping结构体对象)。
4、如果是模糊查询则替换*为所有可能的tag key与field key(获取tag key时,实际上已经访问了TSI索引)。
5、校验查询类型是否合法。
6、确定与查询间隔(group by time())匹配的开始和结束时间并再次校验查询buckets是否超过了max-select-buckets配置项。

Select过程

在InfluxDB内部,由5种Iterator,它们分别是buildFieldIterator、buildAuxIterator、buildExprIterator、buildCallIterator和buildVarRefIterator。它们根据不同的查询产生不同的创建过程,彼此组成互相调用的关系,并组成了最终的cursor。

在Select函数构建cursor的过程中,调用不断向下,我们最终会来到Engine.CreateIterator函数的调用。Engine与一个shard对应,如果查询跨多个shard,在外层会遍历所有涉及本次查询的shards(LocalShardMapping),对每个shard对应的Engine执行CreateIterator,负责查询落在本shard的数据。根据查询究竟是查数据,还是聚合函数,Engine.CreateIterator里会调用createVarRefIterator或者createCallIterator。

它们最终都会调用createTagSetIterators函数,调用之前,会查询出所有的series作为调用参数(这里访问了索引TSI)。接下来,程序会以series和cpu核数的较小值为除数平分所有的series,然后调用createTagSetGroupIterators函数继续处理,其内部会对分配到的series进行遍历,然后对每一个seriesKey调用createVarRefSeriesIterator函数。在createVarRefSeriesIterator函数中,如果ref有值,则直接调用buildCursor函数。如果ref为nil,则opt.Aux参数包含了要查询的fields,所以对其进行遍历,对每个feild,再调用buildCursor函数。

buildCursor函数中,先根据measurement查询到对应的fields,再根据field name从fields中查询到对应的Field结构(包含feild的ID、类型等)。然后,根据field是什么类型进行区别,比如是float类型,则调用buildFloatCursor函数。各类型的buildCursor底层调用的实际是TSM文件访问的函数,新建cursor对象时(newKeyCursor)使用fs.locations函数返回所有匹配的TSM文件及其中的block(KeyCursor.seeks),读取数据时则是根据数据类型调用peekTSM()、nextTSM()等TSM访问函数。

查询倒排索引TSI

我们先看一张基于TSI的InfluxDB索引组织图(如下所示)。其中db(数据库)、rp(存储策略)、shard、Index在文件组织下都是以目录形式表现,TSI使用了分区策略,所以在Index文件夹下是0~7共计8个partition文件夹,partition文件夹则是TSI文件与它的WAL(TSL):


TEST3


LSMベースのメカニズムを使用して、TSIは、動作が追加専用モードでフォーマットログ・エントリWALに書き込まれる(TSLファイル、対応するレベルが0である)、修正及び削除操作も、背景圧縮(レベル0〜レベル1)プロセスは、真のデータの削除になります。締固め作業は、TSLファイルを実行したときに実際に新しいファイルへのWAL TSI TSIフォーマット変換に書き込まれます。プロセスの小型、コンパクトな性質のためにローレベルからハイレベルに定期的TSIファイル(レベル1-LEVEL6)はtagbockの同じ測定、一緒に置くために対応する全てのtagvalue同じtagkey同じ測定、及び同一の同tagkey同じ測定に協力します組み合わせのためtagvalue異なるシリーズID。

のは、クエリが実行されたとき、InfluxDBに対応する測定、タグキー、TSMのタグ値と関連付けられたデータファイルを見つけるためにそれを使用する方法を理解するために、TSIファイルの内部構造を見てみましょう。

index_file

まず、TSDB /インデックス/ tsi1 / index_file.go持っている非常に興味深い定数IndexFileTrailerSizeを参照してください。

IndexFileTrailerSize = IndexFileVersionSize +
    8 + 8 + // measurement block offset + size
    8 + 8 + // series id set offset + size
    8 + 8 + // tombstone series id set offset + size
    8 + 8 + // series sketch offset + size
    8 + 8 + // tombstone series sketch offset + size
    0

その定義から、それを描くのは簡単です:
1、IndexFileTrailerSizeは、ファイルの末尾に固定82bytes TSIを占め、それはトレーラーTSI解析時に読みやすい
2を、その定義によって、私たちは基本的にTSIが含まれているものを知っていますセクション:


TEST4


ここでは、我々は慎重に、後で1.7のコードを分析し、私はこのエリアに設定非常に興味深い質問、シリーズIDは、お問い合わせの際に一連の重要な役割を確認するために、一連のidで再生できませんでした。実際には、1.7 influxdbは、唯一のシリーズIDシリーズのキーのマッピングを格納するために、このフォルダには、特別なフォルダ_seriesがあります。

測定ブロック

私たちは、TSDB /インデックス/ tsi1 / measurement_block.goで定義されている測定ブロック、を見て、我々はまた、測定ブロックも同様のメタ情報保存された予告編や他のさまざまな部品を作っ見つけるのは非常に簡単です。

MeasurementTrailerSize = 0 +
    2 + // version
    8 + 8 + // data offset/size
    8 + 8 + // hash index offset/size
    8 + 8 + // measurement sketch offset/size
    8 + 8 // tombstone measurement sketch offset/size


TEST5


(1)トレーラーMeasuermentBlock部分が他の部分に格納された全体指標、オフセットおよびサイズです。

(2)データは全てMeasurementBlockElementの組の/サイズの部分を相殺します。測定、ファイル内の対応するタグ回収並びにオフセットとサイズ、現在の測定シリーズID情報の全ての名前の中に含まMeasurementBlockElement。

ハッシュ・インデックスに格納されている(3)ハッシュインデックス部分は、ファイルが迅速に全体TSIを読まずオフセットMeasurementBlockElementを見つけることができ、ファイル内のオフセットMeasurementBlockElement。

(4)測定スケッチと墓石測定スケッチは、統計目的のためのベースとして使用するHyperLogLog ++アルゴリズムです。

タグブロック

私たちは、TSDB /インデックス/ tsi1 / tag_block.goで定義されているタグブロックを、見て、トレーラーも同様の定義があります。

const TagBlockTrailerSize = 0 +
  8 + 8 + // value data offset/size
  8 + 8 + // key data offset/size
  8 + 8 + // hash index offset/size
  8 + // size
  2 // version

メタ情報に対応する(1)トレーラータグブロックは、オフセットおよび他の成分を保持する各ファイルのサイズ。

(2)鍵データは、2つの内部ハッシュインデックスを有するデータブロック部分鍵タグの一部であり、迅速にタグ鍵ブロック・タグ・キーを介して指定された部分に配置することができ、データは、すべてのタグが現在のタグキーに対応するデータサイズ区分点をオフセット値ブロックファイル領域。

(3)意匠部に類似値データ及び鍵データ。タグ値のブロックの中で、シリーズIDは、私たちの主な懸念を設定があります。

(4)ハッシュインデックス部分を、すばやくタグキーによってoffssetタグキーブロックを見つけることができます。

_seriesフォルダ

オリジナルシリーズIDがすべてSeriesKeyのためのデータベース全体を格納する領域を設定し、これは歴史から残された問題かもしれません。influxdbの1.7.7バージョンでは、唯一のシリーズIDシリーズのキーのマッピングを格納するために、このフォルダには、特別なフォルダ_seriesがあります。


画像


ビュー_seriesフォルダのディレクトリ構造、および8つのパーティションに分け、同様のもTSI。_seriesフォルダシリーズシリーズIDによってinfluxdbの最新バージョンでは、ファイルシリーズキーマッピングを取得します。

パケットの同時実行

クエリの後TSIに応じて、すべてのSeriesKey転置インデックスファイルを取得するには、SeriesKey GROUPBY条件、ハッシュのためのグループ化アルゴリズムに従ってグループ化されなければなりません。異なるSeriesKeyのパケット群の後に大幅クエリの性能を向上させる、並列クエリの実行を可能にし、最終的に独立して重合の実行。

概要

各パーティションと、自分のトレーラー、測定ブロックを持っています。最後に、我々は、マルチレベルのインデックス方式で、各レベルは異なる領域にオフセットを見つけることが迅速かつ簡単にトレーラーを、設計されており、総括に来て、TSIファイル形式のデザイン、タグのブロックは、タグブロック内のキーデータは、ハッシュインデックスは、クエリファイルオフセットをスピードアップするために設計されています。

クエリのため、我々は、クエリ条件タグキーに従ってフィルタリング対応MeasurementBlockElementに設定されたタグに測定ブロックの測定に基づいて、その後に対応するタグブロックに関連付けられたすべてのタグ値のブロックを探します。メイドシリーズIDは問い合わせが関与するすべてのSeriesKeyを見つけるために、一連のid _seriseフォルダに応じて、タグ値のブロックに設定してください。

TSMデータ検索

我々は最初のTSMのデザインを見てください。ヘッダー、ブロック、インデックスとフッター:TSMは、次の4つの領域として設計されています。


TEST6


前記4ビットのヘッダ(ファイルの種類を定義するために使用される)マジックナンバーとバージョンナンバーワン。

領域内のブロックは、独立したデータブロックのシリーズは、生成されたCRC32チェックサムアルゴリズムを含む各ブロックは、ブロックの完全性を確保します。内部データは、タイムスタンプデータは、別途、異なる圧縮アルゴリズムに従って圧縮します。図の解体は、次のとおりです。


TEST7


インデックスエリアでは、インデックス・ブロックの領域に格納されます。索引エントリのシリーズによって、インデックスの領域が、後者は辞書順に従って、キーを押してスタンプです。ブロック現在、このブロックの最大値と最小時間オフセットブロックファイル、ブロック長の鍵長、キー、データ・タイプ、数:内部インデックスエントリは、から成ります。


TEST7


フッターファイルを格納する領域は、インデックス領域を相殺しました。

InfluxDB開始後のTSM率層ファイルは、すべてのメモリにロードされ、メモリの過剰消費によるデータ部分がロードされません。:一般的な手順以下のインストールデータを取得する

最初のすべてのエントリインデックスインデックスはSeriesKey TSIが得られたすべてのからの問い合わせに対応する見つけ、1、キーを発注しているので、二分探索の実装を使用することが可能です。
図2に示すように、フィルタのニーズを残り[MINTIME、MAXTIME]インデックスエントリを使用して、その後、すべてのインデックスエントリを見つける見つけるために時間に応じました。
3、索引エントリによって可能なデータブロックのリストに移動します。
図4は、データブロックの状態は、非圧縮データを見つけるためにバイナリサーチアルゴリズムさらにルックアップを使用して、解凍アルゴリズムを使用して、データ型に対応する、メモリにロードされました。

概要

InfluxDBクエリプロセスは、タイミングデータベースを考えに綿密な研究の分野での開発のために非常に適した、透明な絶妙な、モジュール分割を達成するために、論理ソース、より複雑なプロセスです。スペースが限られているので、この記事に関連する部分には完了していない、多くの詳細が原因私はミスの他の場所に記載している可能性があり限られた知識に、読み取り処理に研究コミュニティのオープンソースリファレンスリーダーを比較する必要があり、我々は論文を歓迎します。

アリ雲InfluxDB®が正式に商品化し、ご覧ください購入ページ(https://common-buy.aliyun.com/?commodityCode=hitsdb_influxdb_pre#/buy)ドキュメント(https://help.aliyun.com/document_detail/ 113093.html?SPM = a2c4e.11153940.0.0.57b04a02biWzGa)。

おすすめ

転載: yq.aliyun.com/articles/719105