ガイドをお探しですか?
例、高度な機能、
JSON 型を使用する際の考慮事項については、JSON のベストプラクティスガイドをご覧ください。JSON 型は、JavaScript Object Notation (JSON) ドキュメントを 1 つのカラムに格納します。
ClickHouse Open-Source では、
JSON データ型はバージョン 25.3 で本番環境対応とされています。以前のバージョンでこの型を本番環境で使用することは推奨されません。JSON 型のカラムを宣言するには、次の構文を使用します。
| Parameter | Description | Default Value |
|---|---|---|
max_dynamic_paths | 省略可能なパラメータで、個別に保存される1つの block のデータ全体にわたって、サブカラムとして個別に保存できるパスの数を示します (たとえば、MergeTree テーブルの1つの data part 全体) 。 この上限を超えると、それ以外のすべてのパスは 共有データ と呼ばれる単一の構造にまとめて保存されます。 また、このパラメータを変更せずに動的パスの上限を変更する方法もあります。 | 1024 |
max_dynamic_types | 1 から 255 までの省略可能なパラメータで、型が Dynamic の単一パスカラム内に、個別に保存される1つの block のデータ全体にわたって、何種類の異なるデータ型を個別に保存できるかを示します (たとえば、MergeTree テーブルの1つの data part 全体) 。この上限を超えると、以降の新しい型はすべて shared variant と呼ばれる単一の構造にまとめて保存されます。 | 32 |
some.path TypeName | JSON 内の特定のパスに対する省略可能な型ヒントです。こうしたパスは、指定された型のサブカラムとして常に保存されます。 | |
SKIP path.to.skip | JSON のパース時にスキップする特定のパスを指定する省略可能なヒントです。こうしたパスは JSON カラムには保存されません。指定したパスがネストされた JSONオブジェクトである場合は、そのネストされたオブジェクト全体がスキップされます。 | |
SKIP REGEXP 'path_regexp' | JSON のパース時にパスをスキップするための正規表現を指定する、省略可能なヒントです。この正規表現に一致するすべてのパスは JSON カラムには保存されません。 |
JSON 型を使用する場面
JSON 型は、動的または予測しにくい構造を持つ JSON オブジェクト内の特定のフィールドに対して、クエリ、フィルタリング、集計を行うために設計されています。これは、JSON オブジェクトを個別のサブカラムに分割することで実現されます。これにより、Map や文字列のパースなどの代替手段と比べて、読み取るデータ量を大幅に削減し、選択したフィールドに対するクエリを高速化できます。
ただし、これには重要なトレードオフがあります。
INSERTが遅くなる - JSON をサブカラムに分割し、型推論を行い、柔軟なストレージ構造を管理する必要があるため、JSON を単純なStringカラムとして保存する場合に比べて、INSERTは遅くなります。- オブジェクト全体を読み取る場合は遅くなる - 完全な JSON ドキュメント全体を取得する必要がある場合 (特定のフィールドではなく) 、
JSON型はStringカラムから読み取るよりも低速です。個別のサブカラムからオブジェクトを再構築するオーバーヘッドは、フィールドレベルのクエリを行わない場合にはメリットがありません。 - ストレージのオーバーヘッド - 個別のサブカラムを維持するため、JSON を単一の文字列値として保存する場合に比べて、構造上のオーバーヘッドが増えます。
JSON 型を使用するケース:
- データの構造が動的または予測しにくく、ドキュメントごとにキーが異なる
- フィールドの型やスキーマが時間の経過とともに変化する、またはレコードごとに異なる
- JSON オブジェクト内の特定のパスに対して、構造を事前に予測できなくてもクエリ、フィルタ、集計を行う必要がある
- ユースケースに、スキーマに一貫性のないログ、イベント、ユーザー生成コンテンツなどの半構造化データが含まれる
String カラム (または構造化型) を使用するのは次のような場合です:
- データ構造が明確で一貫している場合。この場合は、代わりに通常のカラム、
Tuple、Array、Dynamic、またはVariant型を使用します JSONドキュメントを不透明なブロブとして扱い、フィールド単位で解析せず、全体をそのまま保存・取得するだけの場合- データベース内で個々の JSON フィールドに対してクエリやフィルタを行う必要がない場合
JSONが単なる転送/保存用のフォーマットであり、ClickHouse 内では解析しない場合
JSON の作成
JSON を作成するさまざまな方法について説明します。
テーブルのカラム定義で JSON を使用する
Query (Example 1)
Response (Example 1)
Query (Example 2)
Response (Example 2)
::JSON を使った CAST
::JSON を使うことで、さまざまな型を CAST できます。
String を JSON に CAST
Query
Response
Tuple から JSON へのCAST
Query
Response
Map から JSON への CAST
Query
Response
JSONパスはフラット化されて保存されます。つまり、は次を返します:ではなく、次ではありません:
a.b.c のようなパスから JSONオブジェクトを整形する際、
そのオブジェクトを { "a.b.c" : ... } として構築すべきか、{ "a": { "b": { "c": ... } } } として構築すべきかを判断できません。
この実装では、常に後者であると見なします。例えば:クエリ
応答
JSON パスをサブカラムとして読み取る
JSON 型では、すべてのパスを個別のサブカラムとして読み取れます。
要求されたパスの型が JSON 型の宣言で指定されていない場合、
そのパスのサブカラムは常に Dynamic 型になります。
たとえば:
Query
Response
Query (Reading JSON paths as sub-columns)
Response (Reading JSON paths as sub-columns)
getSubcolumn 関数を使って、JSON型からサブカラムを読み取ることもできます。
Query
Response
NULL 値で補完されます:
Query
Response
Query
Response
a.b については、JSON型の宣言で指定したとおり、型は UInt32 であり、
それ以外のすべてのサブカラムの型は Dynamic です。
また、Dynamic 型のサブカラムは、特別な構文 json.some.path.:TypeName を使って読み取ることもできます。
Query
Response
Dynamic のサブカラムは、任意のデータ型にキャストできます。この場合、Dynamic 内部の型を要求された型にキャストできない場合は、例外がスローされます。
Query
Response
Query
Response
compact な MergeTree パーツからサブカラムを効率的に読み取るには、MergeTree 設定 write_marks_for_substreams_in_compact_parts が有効になっていることを確認してください。
JSON のサブオブジェクトをサブカラムとして読み取る
JSON 型では、特殊な構文 json.^some.path を使用して、ネストされたオブジェクトを JSON 型のサブカラムとして読み取れます:
Query
Response
Query
Response
パスが基本的な (
map) 共有データ に格納されている場合、共有データ構造全体をスキャンする必要があるため、サブオブジェクトのサブカラムの読み取りは非効率になることがあります。map_with_buckets または advanced の共有データシリアライゼーションでは、共有データからサブカラムを読み取る処理が大幅に最適化されています。JSON 結合サブカラムの読み取り
JSON 型では、特別な構文 json.@some.path を使って、パスを結合サブカラムとして読み取ることができます。
指定したパスの結合サブカラムは、次のいずれかを返します。
- そのパスにリテラル値がある場合は、その値を
Dynamicとして返します。 - そのパスにリテラル値はないものの、ネストしたサブパスがある場合は、そのパスの JSON サブオブジェクトを
Dynamicとして返します。 - そのパスにリテラル値もサブパスも存在しない場合は、
NULLを返します。
json.a) とサブオブジェクトサブカラム (json.^a) を個別にクエリするよりも扱いやすくなります。
次の例では、パス a に対する 3 種類のサブカラムを比較します。
Query
Response
Query
Response
- Row 1:
aにはリテラル42が入っています。json.aはこれをDynamic(Int64)として返し、json.^aは空のサブオブジェクト{}(aの下にネストしたキーがないため) を返し、json.@aはリテラル42を返します。 - Row 2:
aにはネストしたオブジェクトが入っています。json.aはNULLを返し (そのパスにはリテラル値がないため) 、json.^aはサブオブジェクトをJSONとして返し、json.@aもサブオブジェクトをDynamic(JSON)として返します。 - Row 3:
aはまったく存在しません。json.aとjson.@aはどちらもNULLを返し、json.^aは空の{}を返します。
パスが basic (
map) の共有データに格納されている場合、結合サブカラムの読み取りでは共有データ構造全体をスキャンする必要があるため、非効率になることがあります。map_with_buckets または advanced の共有データシリアライゼーションでは、共有データからのサブカラムの読み取りは大幅に最適化されています。パスの型推論
JSON のパース時に、ClickHouse は各 JSON パスに対して最も適切なデータ型を検出しようとします。
これは 入力データからの自動スキーマ推論 と同様に機能し、同じ設定によって制御されます。
- input_format_try_infer_dates
- input_format_try_infer_datetimes
- schema_inference_make_columns_nullable
- input_format_json_try_infer_numbers_from_strings
- input_format_json_infer_incomplete_types_as_strings
- input_format_json_read_numbers_as_strings
- input_format_json_read_bools_as_strings
- input_format_json_read_bools_as_numbers
- input_format_json_read_arrays_as_strings
- input_format_json_infer_array_of_dynamic_from_array_of_different_types
Query
Response
Query
Response
Query
Response
Query
Response
JSON オブジェクトの配列の処理
Array(JSON) 型として解析され、そのパスに対応する Dynamic カラムに挿入されます。
オブジェクトの配列を読み取るには、Dynamic カラムからサブカラムとして取り出すことができます。
Query
Response
Query
Response
JSON 型の max_dynamic_types/max_dynamic_paths パラメータは、デフォルト値より小さく設定されています。
これは、ネストされた JSON オブジェクトの配列でサブカラム数が際限なく増えるのを防ぐために必要です。
では、ネストされた JSON カラムからサブカラムを読み取ってみましょう。
Query
Response
Array(JSON) のサブカラム名を明示せずに済みます。
Query
Response
[] の数は、配列の階層レベルを示します。たとえば、json.path[][] は json.path.:Array(Array(JSON)) に変換されます
それでは、Array(JSON) 内のパスと型を確認してみましょう。
Query
Response
Array(JSON) カラムからサブカラムを読み出してみましょう:
Query
Response
JSONカラムから、サブオブジェクトのサブカラムを読み取ることもできます。
Query
Response
NULL を持つ JSON キーの扱い
null と値が存在しない状態は同等と見なされます。
Query
Response
ドットを含む JSON キーの扱い
a.b と値 42 の組として保存されます。JSONのフォーマット時には、ドットで区切られたパスの各部分に基づいて、常に入れ子のオブジェクトとして構成します:
Query
Response
{"a.b" : 42} は {"a" : {"b" : 42}} の形式に整形されます。
この制限により、次のような有効な JSON オブジェクトもパースできません。
Query
Response
25.8 以降で利用可能) を有効にできます。この場合、パース時に JSON キー内のすべてのドットが
%2E にエスケープされ、フォーマット時に再び元に戻されます。
Query
Response
Query
Response
Query
Response
json.`a.b` はサブカラム json.a.b と同等と見なされるため、ドットをエスケープしたパスは読み取れません:
Query
Response
SKIP / SKIP REGEX セクションで使用する場合) 、ヒント内のドットはエスケープする必要があります。
Query
Response
Query
Response
データからJSON型を読み取る
JSONEachRow,
TSV,
CSV,
CustomSeparated,
Values など) は、JSON 型の読み取りに対応しています。
例:
Query
Response
CSV/TSV などのテキストフォーマットでは、JSON は JSON オブジェクトを含む文字列からパースされます:
Query
Response
JSON 内の動的パス数の上限に達した場合
JSON データ型では、内部的に個別のサブカラムとして保持できるパスの数に上限があります。
デフォルトの上限は 1024 ですが、型宣言で max_dynamic_paths パラメータを使って変更できます。
この上限に達すると、JSON カラムに新たに挿入されるすべてのパスは、単一の共有データ構造に格納されます。
このようなパスも引き続きサブカラムとして読み取れますが、
効率が低下する可能性があります (共有データに関するセクションを参照) 。
この上限は、テーブルが実質的に使えなくなるほど大量の異なるサブカラムが作成されるのを防ぐために必要です。
では、いくつかの異なるシナリオで、上限に達したときに何が起こるかを見ていきましょう。
データのパース中に上限に達した場合
JSONオブジェクトをパースする際、現在のデータブロックで上限に達すると、
以降の新しいパスはすべて共有データ構造に格納されます。次の 2 つのイントロスペクション関数 JSONDynamicPaths, JSONSharedDataPaths を使用できます。
Query
Response
e と f.g を挿入した時点で上限に達したため、
それらは共有データ構造に挿入されました。
MergeTree テーブルエンジンでのデータパーツのマージ時
MergeTree テーブルで複数のデータパーツをマージする際、マージ後に生成されるデータパーツの JSON カラムが動的パスの上限に達し、
元のパーツにあるすべてのパスをサブカラムとして保存できなくなることがあります。
この場合、ClickHouse は、マージ後にどのパスをサブカラムとして残し、どのパスを共有データ構造に保存するかを選択します。
ほとんどの場合、ClickHouse は
非 NULL 値を最も多く含むパスを残し、出現頻度が最も低いパスを共有データ構造に移そうとします。ただし、これは実装に依存します。
では、このようなマージの例を見てみましょう。
まず、JSON カラムを持つテーブルを作成し、動的パスの上限を 3 に設定してから、5 つの異なるパスを持つ値を挿入します:
Query
JSON カラムに 1 つのパスのみを含む個別のデータパートが作成されます:
Query
Response
Query
Response
a、b、c を保持し、パス d と e は共有データ構造へ移しました。
前のセクションで説明したように、max_dynamic_paths の上限に達すると、新しいパスはすべて 1 つの共有データ構造に格納されます。
このセクションでは、共有データ構造の詳細と、そこからパスのサブカラムをどのように読み取るかについて見ていきます。
JSONカラムの内容を調べるために使用する関数の詳細については、「イントロスペクション関数」のセクションを参照してください。
メモリ内では、共有データ構造は、フラット化された JSON パスからバイナリエンコードされた値へのマッピングを格納する、型 Map(String, String) の単なるサブカラムです。
ここからパス サブカラムを抽出するには、この Map カラム内のすべての行を順に走査し、目的のパス とその値を探します。
MergeTree テーブルでは、データはデータパーツに格納され、各パーツがディスク (ローカルまたはリモート) 上にすべての内容を保持します。また、ディスク上のデータはメモリ上とは異なる方法で保存される場合があります。
現在、MergeTree のデータパーツにおける共有データ構造のシリアライゼーションには、map、map_with_buckets、
advanced の 3 種類があります。
シリアル化バージョンは、MergeTree
設定 object_shared_data_serialization_version
および object_shared_data_serialization_version_for_zero_level_parts
で制御されます
(ゼロレベルパーツはテーブルへのデータ挿入時に作成されるパーツで、merge によって作成されるパーツはより高いレベルになります) 。
注: 共有データ構造のシリアライゼーションの変更がサポートされるのは、
object serialization version が v3 の場合のみです
map シリアル化バージョンでは、共有データはメモリ内で保持される形式と同じ Map(String, String) 型の単一カラムとしてシリアル化されます。この形式のシリアル化からパスのサブカラムを読み取るには、ClickHouse は Map カラム全体を読み取り、要求されたパスをメモリ内で抽出します。
このシリアル化は、データの書き込みや JSON カラム全体の読み取りには効率的ですが、パスのサブカラムを読み取る用途には効率的ではありません。
map_with_buckets シリアル化バージョンでは、共有データは型 Map(String, String) の N 個のカラム (「バケット」) としてシリアル化されます。
各バケットには、パスの一部だけが含まれます。この種のシリアライゼーションからパスのサブカラムを読み取るには、ClickHouse は
1 つのバケットから Map カラム全体を読み取り、要求されたパスをメモリ上で抽出します。
このシリアライゼーションは、データの書き込みや JSON カラム全体の読み取りにはあまり効率的ではありませんが、パスのサブカラムの読み取りにはより効率的です。
必要なバケットからのみデータを読み取るためです。
バケット数 N は、MergeTree 設定の object_shared_data_buckets_for_compact_part (デフォルトは 8)
および object_shared_data_buckets_for_wide_part (デフォルトは 32) で制御されます。
どちらの設定でも、許可される最大値は 256 です。
advanced シリアル化バージョンでは、共有データ は、要求されたパスのデータだけを読み取れるようにする追加情報を保持する特別なデータ構造にシリアル化されます。これにより、パスのサブカラムの読み取り性能を最大化できます。
このシリアライゼーションはバケットもサポートしており、各バケットにはパスの部分集合のみが含まれます。
このシリアライゼーションはデータの書き込みにはかなり非効率なため (そのため、ゼロレベルのパーツでこのシリアライゼーションを使用することは推奨されません) 、JSON カラム全体の読み取りは map シリアライゼーションと比べてやや非効率ですが、パスのサブカラムの読み取りには非常に効率的です。
注: このデータ構造内に追加情報を保持するため、このシリアライゼーションでは
map および map_with_buckets シリアライゼーションと比べてディスク使用量が大きくなります。
新しい 共有データ シリアライゼーションのより詳しい概要と実装の詳細については、ブログ記事を参照してください。
MergeTree パーツ内の JSON の動的パス数を制御する
max_dynamic_paths パラメータを使用することです。
ただし、既存のカラムの max_dynamic_paths を変更するには、ALTER TABLE <table> MODIFY COLUMN <column> JSON(max_dynamic_paths=K) を実行する必要があり、これにより既存のすべてのパーツを書き換えるバックグラウンドミューテーションが開始されます。
このようなミューテーションは非常に高負荷になる可能性があり、完了するまでサーバーのパフォーマンスに影響を及ぼすことがあります。これを避けるため、新しいパーツに対する MergeTree テーブル内の動的パスの上限を変更するのに役立つ、次の 3 つの setting を利用できます。
merge_max_dynamic_subcolumns_in_wide_part- wide パーツへの merge 中に、各 JSON カラムの動的サブカラム数を制限する MergeTree setting。merge_max_dynamic_subcolumns_in_compact_part- compact パーツへの merge 中に、各 JSON カラムの動的サブカラム数を制限する MergeTree setting。max_dynamic_subcolumns_in_json_type_parsing- JSON データを JSON カラムにパースする際に、各 JSON カラムの動的サブカラム数を制限するセッション setting。
max_dynamic_paths パラメータで指定された値を超えることはできません。
イントロスペクション関数
JSONAllPathsJSONAllPathsWithTypesJSONAllValuesJSONDynamicPathsJSONDynamicPathsWithTypesJSONSharedDataPathsJSONSharedDataPathsWithTypesdistinctDynamicTypesdistinctJSONPaths and distinctJSONPathsAndTypes
2020-01-01 の GH Archive データセットの内容を見てみましょう。
Query
Response
Query
Response
ALTER MODIFY COLUMN で JSON 型に変更
JSON 型に変更できます。現時点でサポートされているのは、String 型からの ALTER のみです。
例
Query
Response
Lazy Type Hints (Experimental)
この機能は実験的な機能であり、設定
allow_experimental_json_lazy_type_hints を有効にする必要があります。ALTER TABLE ... MODIFY COLUMN を使って JSONカラムに型ヒントを追加または変更すると、ClickHouse は通常、新しい型ヒントを実体化するためにすべてのデータパーツを書き換えます。大量の履歴データ (数百テラバイト) を持つテーブルでは、これは非常に大きなコストになる可能性があります。
Lazy type hints を使うと、既存データを書き換えることなく、メタデータのみの操作として型ヒントを追加できます。
- 古いパーツ: 型ヒントは、
Dynamicから指定された型へのキャストによってクエリ時に適用されます - 新しいパーツ: 型ヒントは
INSERT時に実体化されます - マージ: 型ヒントはパーツのマージ時に実体化されます
Lazy Type Hints を有効にする
例
Query
Response
ミューテーション が発生していないことの確認
system.mutations テーブルを確認すると、ALTER が ミューテーション を発生させずに完了したことを確認できます:
型ヒントのマテリアライズ
- バックグラウンドでのマージを待つ: ClickHouse は、パーツがマージされる際に型ヒントを自動的にマテリアライズします
- マージを強制する:
OPTIMIZE TABLE test_lazy FINALを使用して、すべてのパーツをすぐにマージします - パーツを書き換える:
ALTER TABLE test_lazy REWRITE PARTSを使用して、新しいメタデータでパーツを書き換えます
制限事項
- この機能は実験的なものであり、今後のバージョンで変更される可能性があります
- クエリ時の型変換は、あらかじめマテリアライズされた型と比べて、特に大きな JSON オブジェクトでは大きなパフォーマンスオーバーヘッドが発生する場合があります
- この機能が適用されるのは
typed_paths(型ヒント) を変更する場合のみです。max_dynamic_paths、SKIP、SKIP REGEXPなどの他の JSON パラメータでは、引き続きミューテーションが必要です
JSON 型の値同士の比較
Query
Response
Variant データ型の比較ルールに従います。
JSON のデータスキッピングインデックス
JSON カラムで 3 つの方法で使用できます。
- 特定のサブカラムに対する索引 — 通常のカラムと同じように、既知の JSON パスに標準のスキップ索引を作成します。これにより、そのパスの 値 に索引が作成されます。
JSONAllPathsを使用したパスベースの索引 — 各 グラニュール に含まれる パスの集合 に索引を付けることで、クエリ対象のパスを含みえない グラニュール をスキップします。JSONAllValuesを使用した値ベースの索引 — テキスト索引 を使用して、すべての JSON パスにまたがる すべての値 に索引を付け、単一の索引で任意の JSON サブカラムに対する全文検索を高速化します。
特定のサブカラムに対する索引
minmax、set、bloom_filter、tokenbf_v1、ngrambf_v1 など) 。
索引式で JSON サブカラムを参照する方法は 2 つあります。
- JSON 型ヒントで宣言された 型付きパス —
json.aのように名前で直接アクセスします。 - 明示的にキャストする 動的パス —
json.b::Stringのように::キャスト構文を使用します。
json.a || json.b::String のように、複数のサブカラムを組み合わせた式も使用できます。
例
Query
data.sensor_id 上の minmax 索引により、スキャン対象は一致するグラニュールに絞り込まれます:
Query
Response
data.location::String に対する bloom_filter 索引も有効です:
Query
Response
JSONAllPaths を使用したパスベースの索引
JSONAllPaths 関数を使用すると、JSON カラムに対しても データスキッピングインデックス を作成できます。
これは、mapKeys を使って Map カラムにスキップ索引を作成する場合と同様です。索引には各グラニュールに存在する JSON パスの集合が格納され、問い合わせ対象のパスを含む可能性がないグラニュールをスキップするために使用されます。
サポートされる索引タイプ
JSONAllPaths は、以下のスキップ索引タイプで使用できます。
bloom_filter—equals、in、IS NOT NULLをサポートします。tokenbf_v1—equalsとIS NOT NULLをサポートします。ngrambf_v1—equalsとIS NOT NULLをサポートします。text(転置索引) —equals、in、IS NOT NULLをサポートします。
例
Query
EXPLAIN indexes = 1 を使用すると、スキップ索引が使われていることを確認できます。あるパスが 1 つのパートにしか存在しない場合、索引はもう一方のパートをスキップします。
Query
Response
Query
Response
IS NOT NULL でも索引が使用されます。パスが存在しないグラニュールはスキップされます (その場合、値は NULL になるためです) 。
Query
Response
仕組み
JSONAllPaths(json_column) 式は、JSON 値内に存在するすべてのパスを含む Array(String) を生成します。
スキップ索引は、これらのパス文字列をそのデータ構造 (bloom filter または転置索引) に格納します。
クエリで json.some.path によるフィルタリングを行うと、索引は各グラニュールについて文字列 "some.path" が含まれているかどうかを確認し、含まれていないグラニュールをスキップします。
欠落したパスに対する安全性
Dynamic型 (例:json.path) およびNullable型のサブカラム (例:json.path.:Int64) ではNULLになります。NULLとの比較は常に false を返すため、スキップは安全です。- 非
Nullableの CAST 式では、その型のデフォルト値になります (例: パスが欠落している場合、json.path::Int64は0になります) 。この場合、比較対象の値がデフォルト値と異なるときにのみ、スキップは安全です。この違いは索引が自動的に処理します。
JSONAllValues を使った全文検索
JSONAllValues 関数を通じて JSON カラムに対する全文検索を高速化できます。
JSONAllValues は JSON カラム内のすべての値を Array(String) として返し、これにテキスト索引を作成できます。
JSONAllValues(json_column) に 1 つの索引を作成するだけで、すべての JSON パスをカバーできるため、各パスごとに個別の索引を作成しなくても、任意のサブカラムに対して全文検索を行えます。
詳細と例については、テキスト索引のドキュメントにある JSONAllValues を使用した値ベースの索引 を参照してください。
JSON 型をより適切に使うためのヒント
JSONカラムを作成してデータを読み込む前に、次の点を検討してください。
- データを調査し、型付きのパスヒントをできるだけ多く指定してください。これにより、保存と読み取りの効率が大幅に向上します。
- 必要になるパスと不要なパスを検討してください。不要なパスは
SKIPセクションで指定し、必要に応じてSKIP REGEXPセクションも使用してください。これにより、ストレージ効率が向上します。 max_dynamic_pathsパラメータは極端に大きな値に設定しないでください。保存と読み取りの効率が低下する可能性があります。 これはメモリや CPU などのシステムパラメータに大きく依存しますが、一般的な目安としては、ローカル filesystem ストレージではmax_dynamic_pathsを 10 000 を超えて設定せず、リモート filesystem ストレージでは 1024 を超えて設定しないことを推奨します。