Skip to content

필사 모드: InfluxDB 3 Core の「72時間制限」は実は432ファイル制限だった — Parquet書き直しが残した請求書

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

はじめに — 72時間という数字の正体

InfluxDB 3を検討したことがある人なら、「オープンソースのCoreは直近72時間までしかクエリできない」という一文をどこかで見たはずです。コミュニティフォーラムにも、比較記事にも繰り返し出てきます。

ところがソースを読んでも、72時間を数えるコードはありません。時間範囲を検査するロジックそのものが存在しないのです。実際に存在するのはこれ一つだけです — クエリ1回が触れられるParquetファイル数の上限。 デフォルト値は432です。

この区別は言葉遊びではありません。制限の単位が時間ではなくファイルであるという事実が、この制限の性質、この制限がいつより早く発動するか、そしてそもそもなぜ存在するのかを全部説明します。そしてその答えは一つのアーキテクチャ上の決定に直結します — ストレージ層をParquetに賭けたという決定です。

本稿はその請求書を読み解きます。時系列DB陣営全体の地図は時系列データベース2026徹底比較で扱ったので、ここではInfluxDB 3一つだけを深掘りします。

432はどこから来たのか

InfluxDB 3 Coreはinfluxdata/influxdbリポジトリでMITまたはApache-2.0として公開されています。だからこれは推測すべき類の問いではありません。読めばいいだけです。

まずフラグの定義です。influxdb3/src/commands/serve.rsのコメントはこう書いています。

/// Set the limit for number of parquet files allowed in a query. Defaults
/// to 432 which is about 3 days worth of files using default settings.
/// This number can be increased to allow more files to be queried, but
/// query performance will likely suffer, RAM usage will spike, and the
/// process might be OOM killed as a result. It would be better to specify
/// smaller time ranges if possible in a query.
#[clap(long = "query-file-limit", env = "INFLUXDB3_QUERY_FILE_LIMIT", action)]
pub query_file_limit: Option<usize>,

フラグはOption型で、値を渡さなければinfluxdb3_write/src/write_buffer/mod.rsでデフォルト値が埋め込まれます。リリースタグv3.10.0基準で437行目です。

query_file_limit: query_file_limit.unwrap_or(432),

では432はなぜ432なのでしょうか。InfluxDB 3は入ってくるデータをタイムスタンプ基準で一定長の時間ブロックに詰め、Parquetファイルとして書き出します。このブロックはgen1と呼ばれ、長さは--gen1-durationで決まります。

/// Duration that the Parquet files get arranged into. The data timestamps will land each
/// row into a file of this duration. 1m, 5m, and 10m are supported. These are known as
/// "generation 1" files. The compactor in Pro can compact these into larger and longer
/// generations.
#[clap(long = "gen1-duration", env = "INFLUXDB3_GEN1_DURATION", default_value = "10m", action)]
pub gen1_duration: Gen1Duration,

デフォルトは10分で、許容値は1分・5分・10分の3つだけです。コード上もDuration::from_secs(600)がデフォルトで、パーサーは60・300・600秒しか通しません。

これで計算が合います。

gen1 ブロック = 10分
1時間あたりのファイル数 = 60 / 10 = 6
1日あたりのファイル数  = 6 x 24 = 144
432 / 144 = 3日 = 72時間

つまり72時間は入力値ではなく派生値です。432というファイル数上限に10分というブロック長を掛けた結果に過ぎません。公式ドキュメントも同じことを言っています — デフォルト値432とデフォルトのgen1-duration10分を使うと、クエリは最大72時間分のデータにアクセスできる、と。

--gen1-durationを1分に下げるとどうなるでしょうか。432ファイルはそのまま432分、約7.2時間になります。同じ432なのに、照会できる範囲は10分の1に縮みます。これが「時間制限ではなくファイル制限だ」という言葉の実質的な意味です。

ハード制限からソフト制限へ

もともとは本当に時間制限でした。初期のInfluxDB 3 Coreにはクエリと書き込みの両方に72時間のハード制限がかかっていて、それを取り払ったのがPR #25890です。GitHub APIで確認したメタデータでは、2025年1月21日にオープンし、1月23日にマージされています。

PR本文の説明は、本稿の要約とほとんど同じです。

  • Coreの72時間クエリ・書き込み制限を撤廃する
  • 代わりにクエリをデフォルトのParquetファイル数で制限する。432を選んだのは、gen1タイムブロックのデフォルト設定でおよそ72時間に相当するからである
  • このファイル上限は引き上げられるが、ヘルプとエラーメッセージでクエリ性能が悪化することを警告する
  • このエラーに遭遇したら、可能な限り狭い時間範囲を使うよう警告する

そして最後の一文が核心です — ハード制限を撤廃し、ユーザーが性能上の代償を受け入れて選べるソフト制限に置き換える。ただしその代償を受け入れられないなら、コンパクターが組み込まれたEnterpriseへの移行を勧める。

この文章は2025年1月に書かれ、2026年7月時点でもそのまま有効です。

72時間は最良のケースにすぎない

ここが実務者が驚くポイントです。ドキュメントは432と10分を掛けると72時間になると述べたあと、すぐに但し書きを付けます — ただし、与えられた10分ブロックのデータがすべて同時に取り込まれたかどうかによって、それより短くなり得る、と。

理由はファイルパスを作るコードを見れば明らかです。influxdb3_write/src/paths.rsです。

{host_prefix}/dbs/{db_id}/{table_id}/{YYYY-MM-DD}/{HH-MM}/{wal_seq}.parquet

ディレクトリまでがgen1ブロック(日付+時・分)であり、ファイル名はWALシーケンス番号です。つまり一つの10分ブロックの中に、異なるWALシーケンスで作られた複数のファイルが共存し得ます。同じ10分に対してスナップショットが2回起きればファイルが2つできて、そのブロックはファイル予算432のうち2つを消費します。

デフォルト設定ではこれがあまり起きないよう調整されています。--wal-flush-intervalのデフォルトは1秒、--wal-snapshot-sizeのデフォルトは600で、フラグの説明どおりこの2つを掛けた値がスナップショット周期を決めます。600秒は10分なので、スナップショット周期はgen1ブロックの長さとぴったり一致し、ブロックあたりファイル1つになります。

問題は、データが常におとなしく届くとは限らないことです。過去の時点へバックフィルしたり、遅延到着データがすでにスナップショット済みのブロックに入ってきたりすると、そのブロックにファイルが追加で生まれます。すると432という予算は72時間より早く尽きます。バックフィルが多いワークロードほど、「72時間」という数字はどんどん嘘になっていきます。

まとめると、72時間は保証ではなく上限であり、しかもそれはデータがリアルタイムでしか届かない場合の上限です。

制限に達すると何が起きるか

強制のポイントはwrite_buffer/mod.rsでファイル一覧を数える箇所です。ロジック自体は3行で要約できます — 該当テーブルでフィルタを通過したParquetファイルを集め、個数が上限を超えたらDataFusionのエラーを投げて終了する。

ここで3点押さえておくべきことがあります。

第一に、制限はテーブル単位です。 ファイル一覧を取得する際にデータベースIDとテーブルIDでフィルタするため、432は「クエリ全体」ではなく「クエリが触れる1つのテーブル」の予算です。

第二に、これはスキャン後の失敗ではなく計画段階での拒否です。 ファイルを開いてから遅くなるのではなく、ファイル数を数えたうえで実行そのものを拒否します。部分的な結果もありません。

第三に、エラーメッセージには小さなバグがあります。 メッセージのプレースホルダーに渡すフォーマット引数は、実際にスキャンしようとしていたファイル数ではなく、上限値そのものです。

format!(
    "Query would scan {} Parquet files, exceeding the file limit. \
     InfluxDB 3 Core caps file access to prevent performance degradation \
     and memory issues. Use a narrower time range, or increase the limit \
     with --query-file-limit ...",
    self.query_file_limit
)

引数は1つだけで、その値は上限です。だから5,000ファイル分のクエリを投げても、メッセージは常に「Query would scan 432 Parquet files」となります。どれだけ超過しているのかは、このエラーからはわかりません。時間範囲をどのくらい縮めればいいのか見当をつけたい人には、かなり不親切な挙動です。

メッセージ本文は上限を上げることを勧めていません。より狭い時間範囲を使うか、コンパクターが入ったEnterpriseに移行するよう案内します。非商用・家庭用は無料で、商用評価には無料トライアルがあるという文言まで、エラーメッセージの中に入っています。

上限を上げればいいのでは — オブジェクトストレージの請求書

--query-file-limitを4320に上げて30日分を照会すればいいのでは? できます。ただしドキュメントが列挙する副作用があります。

  • Parquetファイルをより多く読むクエリの性能低下
  • メモリ使用量の増加
  • OOMでinfluxdb3プロセスが落ちる可能性
  • オブジェクトストレージを使っている場合、データアクセスのための多数のGETリクエスト — ドキュメントの表現ではファイルあたり最大2回

最後の項目が静かなキラーです。デフォルトの432だけでも、クエリ1回で最大864回のGETです。これを4320に上げると、ダッシュボードが自動更新するたびにクエリ1回で最大8,640回のGETが発生します。S3のGET単価はリクエスト1,000件単位で課金されるため、これは性能問題である前に請求書問題です。

そしてこれはParquet設計の直接的な帰結です。Parquetファイル1つを読むには、まずフッターのメタデータを読み、それから必要なロウグループを読む必要があります。ファイルが小さく数が多いほど、実データに対するメタデータ往復の比率が悪化します。10分ごとにファイルが1つ落ちる構造は、まさにその最悪の形です。

ドキュメントが出す推奨は率直です — デフォルト設定を維持し、より短い時間範囲を照会せよ。1時間を超えるクエリでより長い範囲や高速な性能が必要なら、Enterpriseを使え。

コンパクターが答えであり、コンパクターは有料である

小さな不変ファイルが積み上がる問題への正しい答えはコンパクションです。小さなファイルを、より長い時間範囲をカバーするより大きなファイルへ書き直し、ファイル数を減らし、シリーズ単位で並べ替え、インデックスを付ける作業です。

InfluxDB 3にはそのコンパクターがあります。Enterpriseにだけです。

これはドキュメントの構造そのものにも表れています。コンパクター専用ノードを立ち上げる--mode=compactの設定例は、ドキュメントのソース上でEnterprise専用のブロックの中にあり、modeオプション自体もEnterprise専用の項目に分類されています。Coreにはコンパクターノードという概念がそもそも存在しません。

Core向けドキュメントの冒頭の一文が、このことを遠回しに語っています — InfluxDB 3 Coreはリアルタイムおよび直近のデータ向けに設計・最適化されたオープンソースの時系列データベースである、と。これはマーケティング文句である前に、アーキテクチャの説明です。コンパクターがないので直近のデータしか見られず、だから直近データ向けと位置づけられているのです。

同じ構造が他の場所でも繰り返されます。CoreのREADMEが誇る性能数値 — last-valueクエリ10ミリ秒未満、distinctメタデータ30ミリ秒未満 — は一般的なクエリ性能ではなく、last-valueキャッシュとdistinct valueキャッシュの性能です。この2つのキャッシュはメモリ上に載せた別構造物です。Parquetのレイアウトの上では「このシリーズの最後の値」のようなポイント照会が速くなり得ないからこそ別に作られたのであり、キャッシュが必要だったという事実自体が、ストレージ層がその種の問いに弱いことの証拠です。

2026年、削除もコンパクターの仕事になる

2026年6月17日にリリースされたv3.10.0で、Enterpriseに行単位の削除が入りました。ところがその実装方式は、本稿のテーマをそのまま繰り返しています。

ドキュメントによれば削除は非同期です。influxdb3 delete rowsを実行すると削除リクエストが記録され、オブジェクトストレージに保存され、コンパクターがそのデータを次に書き直すときにリクエストが適用されます。 デフォルトでは、リクエストから最大24時間まで削除が反映されないことがあり、この遅延は--pt-row-delete-min-ageフラグで調整します。ドキュメントは念を押しています — 削除はコンパクション中に適用されるため、コンパクターがリクエストを処理するまで行は照会され続け、コマンドが返ってきたからといって行が即座に消えると期待してはならない、と。

述語はタグの等価比較しかサポートしません。フィールド値では削除できません。

そしてv3.10.0ドキュメントの既知の問題一覧にはこうあります — 行削除が「完了」と報告されたあとも、まだコンパクションされていない取り込みの末尾部分の行が生き残り、クエリに表示され続けることがある。回避策は、該当データがコンパクションされたあとに削除リクエストを再度入れて行数を確認することです。

これは偶然のバグではなく、設計の論理的帰結です。削除がファイル書き直しとして実装されているなら、まだ書き直されていない領域には削除が存在しません。Parquetファイルは不変だからです。

Core側はどうでしょうか。公式ドキュメントリポジトリでは、Coreの管理ドキュメント一覧にdelete-data.mdがそもそもありません。Enterpriseにしかありません。コンパクターがなければ、行を消す方法もありません。GDPR削除リクエストが来るような種類のデータをオープンソースのCoreに入れているなら、今のうちに確認しておくことをお勧めします。

2026年の本当のニュース — Parquetの上に載る新エンジン

ここまでが背景で、ここからが今年の話です。

2026年4月2日にリリースされたv3.9.0で、InfluxDataは性能アップグレードプレビュー(ベータ)を公開しました。--use-pacha-treeフラグで有効化し、リリースノートの表現では、新しいカラムファイルフォーマット(.ptファイル)、ハイブリッドクエリモードを伴う自動Parquetマイグレーション、幅の広いテーブルI/O向けのカラムファミリー、そして境界のあるコンパクションを含みます。

まとめると、InfluxDBはParquetから部分的に抜け出しつつあります。InfluxDB 3の最初の正式リリースであるv3.0.0は2025年4月16日だったので、GAからおよそ1年です。

理由は推測する必要がありません。ベンダー自身が書いています。プレビュードキュメントの「Why these upgrades」節はこう始まります — 既存のInfluxDB 3ストレージ層はApache Parquetを使っており、分析ワークロード向けに最適化されている。 そして高カーディナリティ・ワイドスキーマ・クエリ集約型のワークロードを回す顧客は、より優れた単一シリーズクエリ性能、より予測可能なリソース使用量、そしてInfluxDB v1とv2を人気にしたスキーマの柔軟性を必要としている。

最後の一節は読み返す価値があります。v1とv2を人気にしたものを取り戻すという文です。v1・v2のストレージエンジンは、時系列専用に作られたTSMそのものであり、3.0で捨てたのはそのTSMでした。

.ptフォーマットの説明を見ると、その回帰はさらにはっきりします。ドキュメントによれば、ファイル内のデータはカラムファミリーキー・シリーズキー・タイムスタンプの順に並び替えられ、データの特性に合わせて型ごとの圧縮アルゴリズムを使います — タイムスタンプにはdelta-delta RLE、浮動小数点にはGorillaエンコーディング、低カーディナリティの文字列には辞書エンコーディングなど。

ここでGorillaが目を引きます。Parquetフォーマット仕様のエンコーディング一覧を直接確認すると、そこにあるのはPLAIN、辞書(PLAIN_DICTIONARY / RLE_DICTIONARY)、RLE、BIT_PACKED(廃止済み)、DELTA_BINARY_PACKED、DELTA_LENGTH_BYTE_ARRAY、DELTA_BYTE_ARRAY、BYTE_STREAM_SPLITの全部です。浮動小数点のXOR系エンコーディング、つまりGorillaは仕様にありません。時系列float圧縮の標準的な手法を使うには、Parquetの外に出るしかなかったのです。

圧縮率についてドキュメントは、一般に5〜20倍を達成すると記しています。ただしこれはベンダー自身の主張であり、どのデータセット・どのスキーマ・どの比較対象を基準にしているのかはドキュメントに書かれていません。比較対象がParquetなのか生のline protocolなのかすら明示されていないため、この数字で容量計画を立てるべきではありません。同様に「高選択性の時系列クエリで一桁ミリ秒の応答」という文言も、測定条件が公開されていません。目標値として読むほうが安全です。

カラムファミリーは、line protocolのフィールド名に::区切りを使って指定します。最初の::より前がファミリー名で、指定しなかったフィールドは自動生成されるファミリーに100個ずつまとめられます。ワイドなテーブルで特定のフィールドだけを照会するとき、それ以外のファミリーブロックをまったく読まなくて済む構造です。

コンパクションも変わります。ドキュメントによれば、コンパクトされたデータは24時間のUTCウィンドウで整理され、Gen0ファイルはL1からL4まで段階を進み、バイト基準のメモリ予算(デフォルトはシステムRAMの半分)の範囲内でバックグラウンドで動き続けます。

プレビューの価値 — 正直に

ここで興奮する前に、ドキュメント自身が付けている警告をそのまま持ってきます。

ベータであり、プロダクション禁止です。 ドキュメントの警告ボックスは、このプレビューがEnterpriseの体験版・有償ユーザーにベータとして提供され、変更があり得るし、プロダクションワークロードに使ってはならないと明記しています。ステージング・テスト環境専用だと釘を刺しています。

v3.10.0の既知の問題にはデータ損失があります。 --use-pacha-treeを有効にした状態でシャードを2個以上(--pt-shard-count)動かすと、データ損失とブートストラップのデッドロックが起きることがあります。回避策はシャード数を1に保つことです。つまり現時点でこのプレビューは実質的に単一シャードでしか使えません。

ダウングレードは元に戻すことではありません。 influxdb3 downgrade-to-parquetはカタログを更新し、すべての.ptファイルをオブジェクトストレージから削除します。ドキュメントの表現では、アップグレード後に書かれたデータも含めて削除され、アップグレード前に存在していた元のParquetファイルだけが保存されます。 プレビューを有効にして1か月分のデータを溜めたあとに気が変わると、その1か月は消えます。

3.10へのアップグレード自体が片道です。 3.10を初めて起動すると、ディスク上のカタログがv2からv3へ自動的にマイグレーションされ、その後は3.9.x以下のバイナリが同じクラスターデータで起動に失敗します。リリースノートは、カタログディレクトリとカタログチェックポイントオブジェクトを事前にバックアップしておくこと、そのオブジェクトを復元することだけが3.9.xへロールバックする唯一の方法だと記しています。--use-pacha-treeを有効にしていた場合、.ptフォーマットで書かれたデータも3.9.xでは読めません。

そしてこれら全部がEnterprise専用です。 Coreは.ptもカラムファミリーも境界のあるコンパクションも受け取りません。Coreは引き続き432ファイルの予算の中で生きます。

CoreとEnterpriseの温度差は、リリースノートを続けて読むと露骨に見えます。2026年6月25日のv3.9.6、6月30日のv3.10.2とv3.9.7 — この3つのリリースのCore項目はすべて同じ文です。メンテナンスリリースであり、ビルドと依存関係の更新のみを含み、ユーザーが体感する変更はない。同じ日付のEnterprise項目には、コンパクションの重複排除の修正とプロセシングエンジンのトリガーキャンセルの修正が入っています。

では、いつ使い、いつ使うべきでないか

Coreで十分な場合。 Coreは悪い製品ではありません。自分がやると言ったことをやります。

  • 照会範囲が直近数時間〜数日のリアルタイムダッシュボードとアラート
  • エッジ・IoT収集ポイントでバッファリングしてから上流へ渡す用途
  • 最新値の照会が中心のワークロード — last-valueキャッシュはまさにこのためにあります
  • データがリアルタイムでしか届かず、バックフィルがないパイプライン

Coreでは足りない場合。 以下のうち一つでも当てはまるなら、オープンソースのCoreは答えではありません。チューニングで乗り越えられる種類の壁ではありません。

  • 数日を超える過去区間を定期的に照会する必要がある — ファイル上限を上げるとGETリクエストとメモリが同時に上がります
  • バックフィルや遅延到着データが頻繁にある — 同じgen1ブロックにファイルが重なって積み上がり、72時間はより早く崩れます
  • 行を削除する必要がある — Coreには方法がありません
  • --gen1-durationを1分に縮める事情がある — 照会可能範囲は7.2時間台まで下がります

Enterpriseプレビューを試す価値がある場合。 ドキュメントが推奨する対象は、高カーディナリティ・ワイドテーブル、時間範囲をまたぐ頻繁なバックフィル、低レイテンシが必要なクエリ集約型のアクセス、動的にカラムが生まれる疎なスキーマ、そしてメモリ・CPU使用量の上限が重要な環境です。ただし、ステージングで、単一シャードで、消えても構わないデータから始めてください。

代替を検討すべき場合。 長期保存と削除と過去照会をすべてオープンソースで済ませる必要があるなら、この選択肢はそもそもInfluxDB 3 Coreではないかもしれません。Postgres拡張へ行くにせよカラムストアへ行くにせよ、比較の出発点は時系列データベース2026徹底比較にまとめてあります。

おわりに

まとめるとこうです。「InfluxDB 3 Coreには72時間制限がある」という文は不正確な要約です。正確には、クエリ1回が1つのテーブルでスキャンできるParquetファイルはデフォルトで432個に制限され、デフォルトのgen1ブロック10分を掛けると72時間になり、その72時間自体も、データがリアルタイムでしか到着しない場合の最良値にすぎません。

この制限は恣意的な機能制限ではありません。Parquetの上に時系列DBを建てると必然的に小さく不変なファイルが大量に生まれ、それを整理する唯一の方法がコンパクションであり、InfluxDataはそのコンパクターを商用の境界線に据えました。オープンソースのCoreはその決定のすべての帰結をそのまま引き継ぎます — ファイル上限、ファイルあたり最大2回のGET、そして削除機能の不在です。

そして2026年、このアーキテクチャの請求書はベンダー自身にも届きました。Parquetが分析ワークロードに最適化されていて、だから単一シリーズクエリとワイドスキーマには力不足だということ — これは私の主張ではなく、InfluxData自身のプレビュードキュメントに書かれていることです。その結果が.ptであり、そこにはParquet仕様にないGorillaエンコーディングが入っています。v1とv2のTSMが持っていた、まさにあの手法です。

教訓があるとすれば、汎用フォーマットを選ぶことの性質についてのものだと思います。Arrow・Parquet・DataFusionを選んだおかげで、InfluxDB 3はSQLとFlight SQLとエコシステムのツールをほぼタダで手に入れました。それは本物の利得でした。ただし汎用フォーマットは汎用的なものに最適化されており、あなたのワークロードがその平均から離れるほど、その差額をどこかで支払うことになります。InfluxDB 3の場合、その差額はコンパクターという名の有料コンポーネントとして、そしてGAから1年で自前のファイルフォーマットを作り直すこととして請求されました。

技術選定を検討するとき、リリースノートの機能一覧より先にこれを見ることをお勧めします — このシステムの根本的な制約は何で、その制約を解くコンポーネントはどちらのライセンス側にあるのか。

参考資料

현재 단락 (1/119)

InfluxDB 3を検討したことがある人なら、「オープンソースのCoreは直近72時間までしかクエリできない」という一文をどこかで見たはずです。コミュニティフォーラムにも、比較記事にも繰り返し出てき...

작성 글자: 0원문 글자: 13,024작성 단락: 0/119