メインコンテンツまでスキップ
バージョン: 4.x

VARIANT

VARIANT

概要

VARIANT型は半構造化JSONデータを格納します。異なるプリミティブ型(整数、文字列、真偽値など)、一次元配列、およびネストされたオブジェクトを含むことができます。書き込み時、DorisはJSONパスに基づいてサブパスの構造と型を推論し、頻繁にアクセスされるパスに対してSubcolumnizationを実行して、柔軟性とパフォーマンスの両方を実現するために独立した列型サブカラムとして公開します。

VARIANTを選ぶ理由

VARIANTは、フィールドが時間の経過とともに変化するが、クエリが依然として少数のホットパスに依存する場合に適しています。

  • ホットパスはSubcolumnizationに参加するため、列型パフォーマンス、ファイルプルーニング、およびベクトル化実行の恩恵を受けます。
  • キーパスはパスレベルインデックス、全文検索を使用でき、Dorisスパースインデックスプルーニングの恩恵も受けられます。
  • Doris 3.1以降では、ワイドカラム最適化により、10k規模のサブカラムでも自動Subcolumnizationが実用的になります。10k規模のワイドカラムに推奨されるストレージレイアウトであるDOCモードはDoris 4.x以降で利用可能であることに注意してください。3.xについては、チューニングガイダンスについてWorkload Guideを参照してください。
ワークロードを設定する前に

Doris 3.xで初めてVARIANTワークロードを使用する場合は、VARIANT Workload Guideから始めてください。このページは構文、型ルール、インデックス、制限、および設定のリファレンスです。

VARIANTの使用

テーブル作成構文

テーブル作成時にVARIANTカラムを宣言します:

CREATE TABLE IF NOT EXISTS ${table_name} (
k BIGINT,
v VARIANT
)
PROPERTIES("replication_num" = "1");

Schema Template(「拡張型」を参照)で特定のパスを制約する:

この機能はバージョン3.1.0以降でサポートされています。

CREATE TABLE IF NOT EXISTS ${table_name} (
k BIGINT,
v VARIANT <
'id' : INT, -- restrict path id to INT
'message*' : STRING, -- restrict message* prefix to STRING
'tags*' : ARRAY<TEXT> -- restrict tags* prefix to ARRAY<TEXT>
>
)
PROPERTIES("replication_num" = "1");

クエリ構文

-- Access nested fields (returns VARIANT; explicit or implicit CAST is required for aggregation/comparison)
SELECT v['properties']['title'] FROM ${table_name};

-- CAST to a concrete type before aggregation
SELECT CAST(v['properties']['title'] AS STRING) AS title
FROM ${table_name}
GROUP BY title;

-- Query arrays
SELECT *
FROM ${table_name}
WHERE ARRAY_CONTAINS(CAST(v['tags'] AS ARRAY<TEXT>), 'Doris');

プリミティブ型

VARIANTはサブカラムの型を自動的に推論します。サポートされている型は次のとおりです:

サポートされている型
TinyInt
NULL(JSON nullと同等)
BigInt(64ビット)
Double
String(テキスト)
Jsonb
Variant(ネストされたオブジェクト)
Array<T>(一次元のみ)

シンプルなINSERTの例:

INSERT INTO vartab VALUES
(1, 'null'),
(2, NULL),
(3, 'true'),
(4, '-17'),
(5, '123.12'),
(6, '1.912'),
(7, '"A quote"'),
(8, '[-1, 12, false]'),
(9, '{ "x": "abc", "y": false, "z": 10 }'),
(10, '"2021-01-01"');

ヒント: 日付/時刻などの非標準のJSONタイプは、Schema Templateが提供されない限り文字列として保存されます。計算効率を向上させるために、静的カラムに抽出するか、Schema Templateでタイプを宣言することを検討してください。

拡張タイプ (Schema Template)

この機能はバージョン3.1.0以降でサポートされています。

プリミティブタイプに加えて、VARIANTはSchema Templateを通じて以下の拡張タイプをサポートしています:

  • Number (拡張)
    • Decimal: Decimal32 / Decimal64 / Decimal128 / Decimal256
    • LargeInt
  • Datetime
  • Date
  • IPV4 / IPV6
  • Boolean
  • ARRAY<T> (Tは上記のいずれかで、一次元のみ)

注意: 事前定義されたSchemaはテーブル作成時にのみ指定できます。ALTERは現在サポートされていません(将来のバージョンでは新しいサブカラム定義の追加をサポートする可能性がありますが、既存のサブカラムタイプの変更はサポートされません)。

例:

CREATE TABLE test_var_schema (
id BIGINT NOT NULL,
v1 VARIANT<
'large_int_val': LARGEINT,
'string_val': STRING,
'decimal_val': DECIMAL(38, 9),
'datetime_val': DATETIME,
'ip_val': IPV4
> NULL
)
PROPERTIES ("replication_num" = "1");

INSERT INTO test_var_schema VALUES (1, '{
"large_int_val" : "123222222222222222222222",
"string_val" : "Hello World",
"decimal_val" : 1.11111111,
"datetime_val" : "2025-05-16 11:11:11",
"ip_val" : "127.0.0.1"
}');

SELECT variant_type(v1) FROM test_var_schema;

+----------------------------------------------------------------------------------------------------------------------------+
| variant_type(v1) |
+----------------------------------------------------------------------------------------------------------------------------+
| {"datetime_val":"datetimev2","decimal_val":"decimal128i","ip_val":"ipv4","large_int_val":"largeint","string_val":"string"} |
+----------------------------------------------------------------------------------------------------------------------------+

{"date": 2020-01-01}{"ip": 127.0.0.1}は無効なJSONテキストです。正しい形式は{"date": "2020-01-01"}{"ip": "127.0.0.1"}です。

Schema Templateが指定されると、JSON値が宣言された型と競合し、変換できない場合、NULLとして保存されます。例えば:

INSERT INTO test_var_schema VALUES (1, '{
"decimal_val" : "1.11111111",
"ip_val" : "127.xxxxxx.xxxx",
"large_int_val" : "aaabbccc"
}');

-- Only decimal_val remains
SELECT * FROM test_var_schema;

+------+-----------------------------+
| id | v1 |
+------+-----------------------------+
| 1 | {"decimal_val":1.111111110} |
+------+-----------------------------+

スキーマは永続化ストレージの型のみを指定します。クエリ実行時には、実際の型は実行時の実際のデータに依存します:

-- At runtime v['a'] may still be STRING
SELECT variant_type(CAST('{"a" : "12345"}' AS VARIANT<'a' : INT>)['a']);

ワイルドカードマッチングと順序:

CREATE TABLE test_var_schema (
id BIGINT NOT NULL,
v1 VARIANT<
'enumString*' : STRING,
'enum*' : ARRAY<TEXT>,
'ip*' : IPV6
> NULL
)
PROPERTIES ("replication_num" = "1");

-- If enumString1 matches both patterns, the first matching pattern in definition order (STRING) is used

カラム名に * が含まれており、それをリテラル名として一致させたい場合(プレフィックスワイルドカードとしてではなく)は、以下を使用してください:

v1 VARIANT<
MATCH_NAME 'enumString*' : STRING
> NULL

マッチしたサブパスはデフォルトでSubcolumnizationに参加し、列として公開されます。マッチするパスが多すぎて過剰な列が生成される場合は、variant_enable_typed_paths_to_sparseの有効化を検討してください(「Configuration」を参照)。

型の競合と昇格ルール

同じパス上で互換性のない型が現れた場合(例:同じフィールドがintegerとstringの両方として現れる場合)、情報の損失を避けるために型はJSONBに昇格されます:

{"a" : 12345678}
{"a" : "HelloWorld"}
-- a will be promoted to JSONB

昇格ルール:

Source typeCurrent typeFinal type
TinyIntBigIntBigInt
TinyIntDoubleDouble
TinyIntStringJSONB
TinyIntArrayJSONB
BigIntDoubleJSONB
BigIntStringJSONB
BigIntArrayJSONB
DoubleStringJSONB
DoubleArrayJSONB
Array<Double>Array<String>Array<Jsonb>

厳密な型が必要な場合(安定したインデックス作成とストレージのため)は、Schema Templateを使用してそれらを宣言してください。

Variantインデックス

インデックスの選択

VARIANTはサブパス上でBloomFilterとInverted Indexをサポートしています。

  • 高カーディナリティの等価性/INフィルタ:BloomFilterを使用(よりスパースなインデックス、優れた書き込みパフォーマンス)。
  • トークン化/フレーズ/範囲検索:Inverted Indexを使用し、適切なparser/analyzerプロパティを設定。
...  
PROPERTIES("replication_num" = "1", "bloom_filter_columns" = "v");

-- Use BloomFilter for equality/IN filters
SELECT * FROM tbl WHERE v['id'] = 12345678;
SELECT * FROM tbl WHERE v['id'] IN (1, 2, 3);

VARIANT列に転置インデックスが作成されると、すべてのサブパスは同じインデックスプロパティ(例:parser)を継承します:

CREATE TABLE IF NOT EXISTS tbl (
k BIGINT,
v VARIANT,
INDEX idx_v(v) USING INVERTED PROPERTIES("parser" = "english")
);

-- All subpaths inherit the english parser
SELECT * FROM tbl WHERE v['id_1'] MATCH 'Doris';
SELECT * FROM tbl WHERE v['id_2'] MATCH 'Apache';

サブパスによるIndex

この機能はバージョン3.1.0からサポートされています。

3.1.x/4.0以降では、特定のVARIANTサブパスに対してindexプロパティを指定でき、同じパスに対してトークン化されたものとトークン化されていないinverted indexの両方を設定することも可能です。パス固有のindexには、Schema Templateを介してパスタイプを宣言する必要があります。

-- Common properties: field_pattern (target path), analyzer, parser, support_phrase, etc.
CREATE TABLE IF NOT EXISTS tbl (
k BIGINT,
v VARIANT<'content' : STRING>,
INDEX idx_tokenized(v) USING INVERTED PROPERTIES("parser" = "english", "field_pattern" = "content"),
INDEX idx_v(v) USING INVERTED PROPERTIES("field_pattern" = "content")
);

-- v.content has both tokenized and non-tokenized inverted indexes
SELECT * FROM tbl WHERE v['content'] MATCH 'Doris';
SELECT * FROM tbl WHERE v['content'] = 'Doris';

ワイルドカードパスインデックス:

CREATE TABLE IF NOT EXISTS tbl (
k BIGINT,
v VARIANT<'pattern_*' : STRING>,
INDEX idx_tokenized(v) USING INVERTED PROPERTIES("parser" = "english", "field_pattern" = "pattern_*"),
INDEX idx_v(v) USING INVERTED -- global non-tokenized inverted index
);

SELECT * FROM tbl WHERE v['pattern_1'] MATCH 'Doris';
SELECT * FROM tbl WHERE v['pattern_1'] = 'Doris';

注意: 2.1.7以降はInvertedIndex V2プロパティのみをサポートします(ファイル数が少なく、書き込みIOPSが低い、分散ストレージ/コンピュートに適している)。2.1.8以降はオフラインBuild Indexを削除します。

インデックスが機能しない場合

  1. 型変更によるインデックスの喪失: サブパスが互換性のない型に変更された場合(例: INT → JSONB)、インデックスが失われます。Schema Templateによる型とインデックスの固定で修正してください。

  2. クエリ型の不一致:

    -- v['id'] is actually STRING; using INT equality causes index not to be used
    SELECT * FROM tbl WHERE v['id'] = 123456;
  3. インデックスの設定ミス: インデックスはサブパスに適用され、VARIANT列全体には適用されません。

    -- VARIANT itself cannot be indexed as a whole
    SELECT * FROM tbl WHERE v MATCH 'Doris';

    -- If whole-JSON search is needed, store a duplicate STRING column and index it
    CREATE TABLE IF NOT EXISTS tbl (
    k BIGINT,
    v VARIANT,
    v_str STRING,
    INDEX idx_v_str(v_str) USING INVERTED PROPERTIES("parser" = "english")
    );
    SELECT * FROM tbl WHERE v_str MATCH 'Doris';

Variant Nested Group

Variant Nested Groupは、VARIANT内のarray<object>値に対する4.1.x版のストレージおよび検索機能であり、オブジェクトのトップレベル配列も含みます。有効にすると、Dorisは配列要素ごとにネストされたオブジェクトのサブパスを整理します。これは、オブジェクトの配列を含むログ、トレース、イベント詳細、その他のレコードに有用です。

主要なクエリセマンティクスは同一要素マッチングです。行に複数のitems要素が含まれる場合、msg:hello AND title:newsは両方の述語が同一の配列要素内で真である場合のみマッチし、異なる要素間での偶発的なマッチを回避します。

Nested Groupの有効化

新しいテーブルでは、必要なVARIANTカラムでNested Groupを明示的に有効にします:

CREATE TABLE variant_nested_group_tbl (
id INT,
data VARIANT<PROPERTIES("variant_enable_nested_group" = "true")>,
INDEX idx_data (data) USING INVERTED PROPERTIES("parser" = "english")
) ENGINE=OLAP
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_num" = "1"
);

テーブルを作成する前にセッションのデフォルトを設定することもできます:

SET default_variant_enable_nested_group = true;

列プロパティとセッション変数の両方が設定されている場合、列プロパティが優先されます。このプロパティはテーブル作成時にのみ指定でき、ALTERで変更することはできません。

ネストした配列の書き込みと読み込み

Nested Groupは、オブジェクト内の配列パスとトップレベル配列をサポートします:

INSERT INTO variant_nested_group_tbl VALUES
(1, '{"items":[{"msg":"hello","title":"news"},{"msg":"foo","title":"bar"}]}'),
(2, '{"items":[{"msg":"hello"},{"title":"news"}]}'),
(3, '[{"msg":"hello","title":"news"}]'),
(4, NULL);

-- Read an array path inside an object
SELECT id, CAST(data['items'] AS STRING)
FROM variant_nested_group_tbl
ORDER BY id;

-- A top-level array is still read through the VARIANT column itself
SELECT id, CAST(data AS STRING)
FROM variant_nested_group_tbl
WHERE id = 3;

ネストされた検索

VARIANT列に転置インデックスを作成した後、SEARCH DSLでNESTED(path, predicate)を使用して、同じネストされた配列要素内で述語を組み合わせます:

-- Same-element match under object field items. This matches only row 1.
SELECT id
FROM variant_nested_group_tbl
WHERE SEARCH('NESTED(data.items, msg:hello AND title:news)')
ORDER BY id;

-- Same-element match on a top-level array. This matches only row 3.
SELECT id
FROM variant_nested_group_tbl
WHERE SEARCH('NESTED(data, msg:hello AND title:news)')
ORDER BY id;

-- Single-field match
SELECT id
FROM variant_nested_group_tbl
WHERE SEARCH('NESTED(data.items, msg:hello)')
ORDER BY id;

NESTED内のフィールドは、ネストされたパスに対して相対的でなければなりません。例えば、NESTED(data.items, data.items.msg:hello)ではなく、NESTED(data.items, msg:hello)を使用してください。内部述語は通常のSEARCH DSL用語、フレーズ、ANY/ALL、およびAND/OR/NOTをサポートしますが、ネストされたNESTED()呼び出しはサポートされていません。

完全なトップレベル配列の例

VARIANT列自体がオブジェクトのトップレベル配列である場合は、NESTEDパスとして列名を直接使用してください。以下の例では、行2は異なる配列要素にmsg=hellotitle=newsを持つため、同一要素のANDクエリは行2にマッチしません:

CREATE TABLE variant_top_array_tbl (
id INT,
data VARIANT<PROPERTIES("variant_enable_nested_group" = "true")>,
INDEX idx_data (data) USING INVERTED PROPERTIES("parser" = "english")
) ENGINE=OLAP
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_num" = "1"
);

INSERT INTO variant_top_array_tbl VALUES
(1, '[{"msg":"hello","title":"news"},{"msg":"foo","title":"bar"}]'),
(2, '[{"msg":"hello"},{"title":"news"}]'),
(3, '[{"msg":"hello","title":"sports"}]');

-- Read the top-level array
SELECT id, CAST(data AS STRING)
FROM variant_top_array_tbl
ORDER BY id;

-- Same-element match for msg=hello and title=news. This matches only id=1.
SELECT id
FROM variant_top_array_tbl
WHERE SEARCH('NESTED(data, msg:hello AND title:news)')
ORDER BY id;

-- Single-field match for msg=hello. This matches id=1, 2, and 3.
SELECT id
FROM variant_top_array_tbl
WHERE SEARCH('NESTED(data, msg:hello)')
ORDER BY id;

explodeで配列を展開する

投影やフィルタリングのために配列要素を行に展開するには、LATERAL VIEW explodeを使用します。Nested Groupテーブルでは、非トップレベル配列とトップレベル配列はexplodeに渡す式のみが異なります:

  • 非トップレベル配列:data['items']のような配列パスを渡す
  • トップレベル配列:dataのようなVARIANTカラム自体を渡す
-- Non-top-level array: expand elements under object field items
SELECT
id,
CAST(e['msg'] AS STRING) AS msg,
CAST(e['title'] AS STRING) AS title
FROM variant_nested_group_tbl
LATERAL VIEW explode(data['items']) tmp AS e
WHERE CAST(e['msg'] AS STRING) = 'hello'
ORDER BY id, title;

-- Top-level array: expand the VARIANT column itself
SELECT
id,
CAST(e['msg'] AS STRING) AS msg,
CAST(e['title'] AS STRING) AS title
FROM variant_top_array_tbl
LATERAL VIEW explode(data) tmp AS e
WHERE CAST(e['msg'] AS STRING) = 'hello'
ORDER BY id, title;

explodeは各配列要素を行として返し、各要素はVARIANTサブパスを通じてアクセスできます。インデックス付き同一要素マッチングにはSEARCH('NESTED(...)')を使用してください。さらなる計算やフィルタリングの前に要素を行にフラット化する必要がある場合は、LATERAL VIEW explode(...)を使用してください。

互換性と制限

  • variant_enable_nested_group = truevariant_enable_doc_mode = trueと相互排他的です。
  • variant_enable_nested_group = truevariant_max_subcolumns_count > 0と相互排他的です。Nested Groupを有効にした後、カラムはもはやsparse-columnプロパティを使用しません。
  • レガシーのvariant_enable_flatten_nestedスイッチは非推奨であり、variant_enable_nested_groupと同じ機能ではありません。4.1.x新規テーブルでは、variant_enable_nested_groupを使用してください。
  • BEコンフィグvariant_nested_group_max_depthは、Nested Groupによって追跡される最大ネストされた配列の深度を制御します。デフォルトは10で、より深いパスはJSONBとして格納されます。
  • 同じパスに対してデータ形状を安定に保ってください。同じパスがスカラーとarray<object>の両方として書き込まれた場合、競合処理がトリガーされ、デフォルトでネストされた配列構造が優先されます。

INSERTとロード

INSERT INTO VALUES

CREATE TABLE IF NOT EXISTS variant_tbl (
k BIGINT,
v VARIANT
) PROPERTIES("replication_num" = "1");

INSERT INTO variant_tbl VALUES (1, '{"a" : 123}');

select * from variant_tbl;
+------+-----------+
| k | v |
+------+-----------+
| 1 | {"a":123} |
+------+-----------+

-- v['a'] is a VARIANT
select v['a'] from variant_tbl;
+--------+
| v['a'] |
+--------+
| 123 |
+--------+

-- Accessing a non-existent key returns NULL
select v['a']['no_such_key'] from variant_tbl;;
+-----------------------+
| v['a']['no_such_key'] |
+-----------------------+
| NULL |
+-----------------------+

Load (Stream Load)

# Line-delimited JSON (one JSON record per line)
curl --location-trusted -u root: -T gh_2022-11-07-3.json \
-H "read_json_by_line:true" -H "format:json" \
http://127.0.0.1:8030/api/test_variant/github_events/_stream_load

関連項目: https://doris.apache.org/docs/dev/data-operate/import/complex-types/variant

読み込み後、SELECT count(*)で確認するか、SELECT * ... LIMIT 1でサンプルを取得してください。高スループットの取り込みの場合は、RANDOMバケッティングを使用し、Group Commitを有効にしてください。

Output

VARIANT列を読み取る際に返されるJSONテキストは、書き込まれたJSONテキストとバイト単位で完全に同一ではありません。JSONオブジェクト内では、入力JSONでのキーの出現順序に関係なく、キーはソート済み(辞書順)の順序で出力されます。

INSERT INTO variant_tbl VALUES
(2, '{ "b": 2, "a": 1, "c": { "y": 20, "x": 10 } }');

SELECT v FROM variant_tbl WHERE k = 2;
+-----------------------------------+
| v |
+-----------------------------------+
| {"a":1,"b":2,"c":{"x":10,"y":20}} |
+-----------------------------------+

ソートはすべてのレベルで適用されます — トップレベルキーは abc になり、ネストされたオブジェクトのキーは xy になります。

サポートされる操作とCASTルール

  • VARIANTは他の型と直接比較/操作することはできません。2つのVARIANT間の比較もサポートされていません。
  • 比較、フィルタリング、集約、および順序付けには、サブパスを具体的な型に(明示的または暗黙的に)CASTしてください。
-- Explicit CAST
SELECT CAST(v['arr'] AS ARRAY<TEXT>) FROM tbl;
SELECT * FROM tbl WHERE CAST(v['decimal'] AS DECIMAL(27, 9)) = 1.111111111;
SELECT * FROM tbl WHERE CAST(v['date'] AS DATE) = '2021-01-02';

-- Implicit CAST
SELECT * FROM tbl WHERE v['bool'];
SELECT * FROM tbl WHERE v['str'] MATCH 'Doris';
  • VARIANT自体はORDER BY、GROUP BY、JOIN KEY、または集約引数として直接使用することはできません。代わりにサブパスをCASTしてください。
  • 文字列はVARIANTに暗黙的に変換できます。
VARIANTCastableCoercible
ARRAY
BOOLEAN
DATE/DATETIME
FLOAT
IPV4/IPV6
DECIMAL
MAP
TIMESTAMP
VARCHAR
JSON

制限事項

  • variant_enable_nested_group = truevariant_enable_doc_mode = trueおよびvariant_max_subcolumns_count > 0と相互排他的です。テーブル作成時にのみ指定できます。
  • NESTED()内のフィールドはネストされたパスに対する相対パスである必要があり、ネストしたNESTED()呼び出しはサポートされていません。
  • variant_max_subcolumns_count (3.1+): デフォルト0(制限なし)。本番環境では、Subcolumnizationを通過するパス数を制御するために2048(タブレットレベル)に設定してください。しきい値を超えると、頻度が低い/スパースなパスは共有データ構造に移動され、そこからの読み取りは遅くなる可能性があります(「Configuration」を参照)。
  • Schema Template(3.1+)でパスタイプが指定されている場合、そのパスはSubcolumnizationに強制されます。variant_enable_typed_paths_to_sparse = trueの場合、それもしきい値にカウントされ、共有構造に移動される可能性があります。
  • JSONキーの長さは≤ 255です。
  • プライマリキーまたはソートキーにはできません。
  • 他の型内にネストできません(例:Array<Variant>Struct<Variant>)。
  • VARIANT列全体を読み取ると、すべてのサブパスがスキャンされます。列に多くのサブパスがある場合、LIKEなどのオブジェクト全体検索のために、元のJSON文字列を追加のSTRING/JSONB列に保存することを検討してください:
CREATE TABLE example_table (
id INT,
data_variant VARIANT
);
SELECT * FROM example_table WHERE data_variant LIKE '%doris%';

-- Better: keep the original JSON string for whole-object matching
CREATE TABLE example_table (
id INT,
data_string STRING,
data_variant VARIANT
);
SELECT * FROM example_table WHERE data_string LIKE '%doris%';

Configuration

バージョン3.1.0以降、以下のすべての列レベルVARIANTプロパティがサポートされています。これらはテーブル作成時にのみ指定可能で、ALTERを使用して変更することはできません。

CREATE TABLE example_table (
id INT,
data_variant VARIANT<
'path_1' : INT,
'path_2' : STRING,
properties(
'variant_max_subcolumns_count' = '2048',
'variant_enable_typed_paths_to_sparse' = 'true'
)
>
);
プロパティ説明
`variant_max_subcolumns_count`Subcolumnizationを通過できるパスの最大数。この閾値を超えると、新しいパスは共有データ構造に格納される可能性があります。デフォルト: 2048(推奨)。0は制限なしを意味します。10000を超えないでください。
`variant_enable_typed_paths_to_sparse`デフォルトでは、型付きパスは常にSubcolumnizationに参加します(`variant_max_subcolumns_count`にはカウントされません)。`true`に設定すると、型付きパスも閾値に対してカウントされ、共有構造に移動される可能性があります。
CREATE TABLE example_nested_group_table (
id INT,
data_variant VARIANT<
properties(
'variant_enable_nested_group' = 'true'
)
>
);
Nested Groupプロパティ説明
`variant_enable_nested_group`Variant Nested Groupを有効にします。`true`に設定すると、オブジェクトのトップレベル配列を含む、`VARIANT`内の`array<object>`値がネストされた要素によって格納され、同一要素マッチングのために`SEARCH('NESTED(...)')`でクエリできます。デフォルトはセッション変数`default_variant_enable_nested_group`に従い、現在のデフォルトは`false`です。このプロパティはテーブル作成時にのみ指定できます。
`default_variant_enable_nested_group`カラムプロパティが指定されていない場合に、新しく作成された`VARIANT`カラムがデフォルトでNested Groupを有効にするかどうかを制御するセッション変数。
`variant_nested_group_max_depth`Nested Groupによって追跡される最大ネスト配列深度を制御するBE設定。デフォルトは10です。

制限時の動作とチューニング提案(項目1-3は3.1+のみに適用):

  1. 閾値を超えた後、新しいパスは共有構造に書き込まれます;Rowsetマージも一部のパスを共有構造にリサイクルする場合があります。
  2. システムはより高い非null比率とより高いアクセス頻度を持つパスをSubcolumnizationに保持することを優先します。
  3. Subcolumnizationで10,000パスに近い場合は強力なハードウェア(ノードあたり≥128G RAM、≥32C推奨)が必要です。
  4. インジェストチューニング:クライアントbatch_sizeを適切に増加するか、Group Commitを使用(必要に応じてgroup_commit_interval_ms/group_commit_data_bytesを増加)。
  5. パーティションプルーニングが不要な場合は、RANDOMバケッティングを検討し、シングルタブレット読み込みを有効にしてコンパクション書き込み増幅を削減。
  6. BEチューニングノブ:max_cumu_compaction_threads(≥8)、vertical_compaction_num_columns_per_group=500(垂直コンパクションを改善するがメモリを増加)、segment_cache_memory_percentage=20(メタデータキャッシュ効率を改善)。
  7. Compaction Scoreを監視;上昇し続ける場合はコンパクションが遅れています—インジェスト圧力を削減。
  8. VARIANTで大きなSELECT *は避け、SELECT v['path']のような特定のプロジェクションを優先。

注意:Stream Loadエラー[DATA_QUALITY_ERROR]Reached max column size limit 2048が表示される場合(2.1.xおよび3.0.xのみ)、マージされたタブレットスキーマがカラム制限に達したことを意味します。variant_max_merged_tablet_schema_sizeを増加できますが(4096を超えることは推奨されません;強力なハードウェアが必要)。

カラム数と型の検査

Solution 1はバージョン3.1.0から対応しています。以前のバージョンでは、DESCの使用を推奨します。

アプローチ1:variant_typeを使用して行ごとのスキーマを検査(より精密、より高コスト):

SELECT variant_type(v) FROM variant_tbl;

アプローチ2:Subcolumnization によって抽出されたサブパスを表示するための DESC の拡張:

SET describe_extend_variant_column = true;
DESC variant_tbl;
DESCRIBE ${table_name} PARTITION ($partition_name);

両方を使用: アプローチ1は正確、アプローチ2は効率的です。

JSON型との比較

  • ストレージ: JSONはJSONB(行指向)として保存されます。VARIANTは書き込み時にSubcolumnizationを使用します(高い圧縮率、小さいサイズ)。
  • クエリ: JSONは解析が必要です。VARIANTは列を直接スキャンし、通常はるかに高速です。

ClickBench(43クエリ):

  • ストレージ: VARIANTはJSONと比較して約65%節約。
  • クエリ: VARIANTはJSONより8倍以上高速で、事前定義された静的列に近い性能。

ストレージ容量

サイズ
Predefined columns12.618 GB
VARIANT12.718 GB
JSON35.711 GB

約65%の容量削減

実行PredefinedVARIANTJSON
First (cold)233.79s248.66sMost timed out
Second (hot)86.02s94.82s789.24s
Third (hot)83.03s92.29s743.69s

FAQ

  1. VARIANTのnullとSQLのNULLは異なりますか?
    • いいえ。それらは等価です。
  2. なぜ私のクエリ/インデックスが動作しないのですか?
    • パスを正しい型にCASTしているか、競合によって型がJSONBに昇格されたか、またはサブパスではなくVARIANT全体にインデックスを期待していないかを確認してください。
  3. Variant Nested Groupと古いvariant_enable_flatten_nestedスイッチの違いは何ですか?
    • variant_enable_flatten_nestedは従来の実験的なスイッチであり、4.1.xの新しいテーブルには推奨されません。variant_enable_nested_groupはネストされたオブジェクトの配列のための新しいストレージおよび検索機能であり、SEARCH('NESTED(...)')による同一要素述語マッチングをサポートします。