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

バリアント

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 bit)
Double
String (Text)
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は上記のいずれでも可能、1次元のみ)

注意: 事前定義された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';

サブパスによるインデックス

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

3.1.x/4.0以降では、特定のVARIANTサブパスに対してインデックスプロパティを指定でき、同じパスに対してトークン化された転置インデックスとトークン化されていない転置インデックスの両方を設定することも可能です。パス固有のインデックスには、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は、両方の述語が同じ配列要素内でtrueの場合にのみマッチし、異なる要素間での偶発的なマッチを回避します。

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を有効にした後、カラムはスパースカラムプロパティを使用しなくなります。
  • レガシーの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 と load

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 = trueは、variant_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'
)
>
);
ネストグループプロパティ説明
`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. システムはより高いnon-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(...)')による同一要素述語マッチングをサポートします。