生成列
v3.1以降、StarRocksは生成列をサポートしています。生成列は、複雑な式を含むクエリを高速化するために使用できます。この機能は、式の結果を事前に計算して保存し、クエリの書き換えをサポートすることで、同じ複雑な式を含むクエリを大幅に高速化します。
テーブル作成時に、式の結果を保存するための1つ以上の生成列を定義できます。このようにして、定義した生成列に結果が保存されている式を含むクエリを実行する際、CBOはクエリを生成列から直接データを読み取るように書き換えます。あるいは、生成列のデータを直接クエリすることもできます。
また、生成列がロードパフォーマンスに与える影響を評価することをお勧めします。なぜなら、式の計算には時間がかかるからです。さらに、テーブル作成時に生成列を作成することをお勧めします。テーブル作成後に生成列を追加または変更するのは時間とコストがかかるためです。
ただし、生成列を持つテーブルにデータがロードされると、StarRocksが式に基づいて結果を計算し、生成列に結果を書き込むため、時間とオーバーヘッドが増加する可能性があることに注意してください。
現在、StarRocksの共有データモードは生成列をサポートしていません。
基本操作
生成列を作成する
構文
<col_name> <data_type> [NULL] AS <expr> [COMMENT 'string']
テーブル作成時に生成列を作成する
5つの列を持つテーブル test_tbl1
を作成し、そのうちの列 newcol1
と newcol2
は、指定された式を使用して通常の列 data_array
と data_json
の値を参照して計算される生成列です。
CREATE TABLE test_tbl1
(
id INT NOT NULL,
data_array ARRAY<int> NOT NULL,
data_json JSON NOT NULL,
newcol1 DOUBLE AS array_avg(data_array),
newcol2 String AS json_string(json_query(data_json, "$.a"))
)
PRIMARY KEY (id)
DISTRIBUTED BY HASH(id);
注意:
- 生成列は通常の列の後に定義する必要があります。
- 集計関数は生成列の式で使用できません。
- 生成列の式は他の生成列や自動インクリメント列を参照できませんが、複数の通常の列を参照することができます。
- 生成列のデータ型は、生成列の式によって生成される結果のデータ型と一致している必要があります。
- 集計テーブルに生成列を作成することはできません。
テーブル作成後に生成列を追加する
ほとんどの場合、クエリ中に頻繁に使用される式はテーブル作成後に決定されるため、生成列はテーブル作成後に追加されることが多いです。パフォーマンスのために、StarRocksがテーブル作成後に生成列を追加するための基盤となるロジックは最適化されています。このため、生成列を追加する際に、StarRocksはすべてのデータを書き換える必要はありません。代わりに、新しく追加された生成列のデータを書き込み、そのデータを既存の物理データファイルと関連付けるだけで済みます。これにより、テーブル作成後に生成列を追加する効率が大幅に向上します。
-
通常の列
id
、data_array
、data_json
を持つテーブルtest_tbl2
を作成し、データ行をテーブルに挿入します。-- テーブルを作成します。
CREATE TABLE test_tbl2
(
id INT NOT NULL,
data_array ARRAY<int> NOT NULL,
data_json JSON NOT NULL
)
PRIMARY KEY (id)
DISTRIBUTED BY HASH(id);
-- データ行を挿入します。
INSERT INTO test_tbl2 VALUES (1, [1,2], parse_json('{"a" : 1, "b" : 2}'));
-- テーブルをクエリします。
MySQL [example_db]> select * from test_tbl2;
+------+------------+------------------+
| id | data_array | data_json |
+------+------------+------------------+
| 1 | [1,2] | {"a": 1, "b": 2} |
+------+------------+------------------+
1 row in set (0.04 sec) -
ALTER TABLE ... ADD COLUMN ...
を実行して、通常の列data_array
とdata_json
の値に基づいて式を評価することで作成される生成列newcol1
とnewcol2
を追加します。ALTER TABLE test_tbl2
ADD COLUMN newcol1 DOUBLE AS array_avg(data_array);
ALTER TABLE test_tbl2
ADD COLUMN newcol2 String AS json_string(json_query(data_json, "$.a"));注意:
- 集計テーブルに生成列を追加することはサポートされていません。
- 通常の列は生成列の前に定義する必要があります。
ALTER TABLE ... ADD COLUMN ...
ステートメントを使用して通常の列 を追加する際に、新しい通常の列の位置を指定しない場合、システムは自動的にそれを生成列の前に配置します。さらに、AFTER を使用して通常の列を生成列の後に明示的に配置することはできません。
-
テーブルデータをクエリします。
MySQL [example_db]> SELECT * FROM test_tbl2;
+------+------------+------------------+---------+---------+
| id | data_array | data_json | newcol1 | newcol2 |
+------+------------+------------------+---------+---------+
| 1 | [1,2] | {"a": 1, "b": 2} | 1.5 | 1 |
+------+------------+------------------+---------+---------+
1 row in set (0.04 sec)結果は 、生成列
newcol1
とnewcol2
がテーブルに追加され、StarRocksが式に基づいてその値を自動的に計算することを示しています。
生成列にデータをロードする
データロード中、StarRocksは式に基づいて生成列の値を自動的に計算します。生成列の値を指定することはできません。以下の例では、INSERT INTO ステートメントを使用してデータをロードします。
-
INSERT INTO
を使用してtest_tbl1
テーブルにレコードを挿入します。VALUES ()
節内で生成列の値を指定することはできません。INSERT INTO test_tbl1 (id, data_array, data_json)
VALUES (1, [1,2], parse_json('{"a" : 1, "b" : 2}')); -
テーブルデータをクエリします。
MySQL [example_db]> SELECT * FROM test_tbl1;
+------+------------+------------------+---------+---------+
| id | data_array | data_json | newcol1 | newcol2 |
+------+------------+------------------+---------+---------+
| 1 | [1,2] | {"a": 1, "b": 2} | 1.5 | 1 |
+------+------------+------------------+---------+---------+
1 row in set (0.01 sec)結果は、StarRocksが式に基づいて生成列
newcol1
とnewcol2
の値を自動的に計算することを示しています。注意:
データロード中に生成列の値を指定すると、以下のエラーが返されます。
MySQL [example_db]> INSERT INTO test_tbl1 (id, data_array, data_json, newcol1, newcol2)
VALUES (2, [3,4], parse_json('{"a" : 3, "b" : 4}'), 3.5, "3");
ERROR 1064 (HY000): Getting analyzing error. Detail message: materialized column 'newcol1' can not be specified.
MySQL [example_db]> INSERT INTO test_tbl1 VALUES (2, [3,4], parse_json('{"a" : 3, "b" : 4}'), 3.5, "3");
ERROR 1064 (HY000): Getting analyzing error. Detail message: Column count doesn't match value count.
生成列を修正する
生成列を修正する際、StarRocksはすべてのデータを書き換える必要があり、時間とリソースを消費します。ALTER TABLE を使用して生成列を修正することが避けられない場合は、事前にコストと時間を評価することをお勧めします。
生成列のデータ型と式を修正できます。
-
通常の列
data_array
とdata_json
の値を参照して指定された式を使用して計算される生成列newcol1
とnewcol2
を持つ5つの列を持つテーブルtest_tbl3
を作成し、データ行をテーブルに挿入します。-- テーブルを作成します。
MySQL [example_db]> CREATE TABLE test_tbl3
(
id INT NOT NULL,
data_array ARRAY<int> NOT NULL,
data_json JSON NOT NULL,
-- 生成列のデータ型と式は次のように指定されています:
newcol1 DOUBLE AS array_avg(data_array),
newcol2 String AS json_string(json_query(data_json, "$.a"))
)
PRIMARY KEY (id)
DISTRIBUTED BY HASH(id);
-- データ行を挿入します。
INSERT INTO test_tbl3 (id, data_array, data_json)
VALUES (1, [1,2], parse_json('{"a" : 1, "b" : 2}'));
-- テーブルをクエリします。
MySQL [example_db]> select * from test_tbl3;
+------+------------+------------------+---------+---------+
| id | data_array | data_json | newcol1 | newcol2 |
+------+------------+------------------+---------+---------+
| 1 | [1,2] | {"a": 1, "b": 2} | 1.5 | 1 |
+------+------------+------------------+---------+---------+
1 row in set (0.01 sec) -
生成列
newcol1
とnewcol2
を修正します:-
生成列
newcol1
のデータ型をARRAY<INT>
に変更し、その式をdata_array
に変更します。ALTER TABLE test_tbl3
MODIFY COLUMN newcol1 ARRAY<INT> AS data_array; -
生成列
newcol2
の式を通常の列data_json
のフィールドb
の値を抽出するように修正します。ALTER TABLE test_tbl3
MODIFY COLUMN newcol2 String AS json_string(json_query(data_json, "$.b"));
-
-
修正後のスキーマとテーブル内のデータを確認します。
-
修正後のスキーマを確認します。
MySQL [example_db]> show create table test_tbl3\G
**** 1. row ****
Table: test_tbl3
Create Table: CREATE TABLE test_tbl3 (
id int(11) NOT NULL COMMENT "",
data_array array<int(11)> NOT NULL COMMENT "",
data_json json NOT NULL COMMENT "",
-- 修正後、生成列のデータ型と式は次のようになります:
newcol1 array<int(11)> NULL AS example_db.test_tbl3.data_array COMMENT "",
newcol2 varchar(65533) NULL AS json_string(json_query(example_db.test_tbl3.data_json, '$.b')) COMMENT ""
) ENGINE=OLAP
PRIMARY KEY(id)
DISTRIBUTED BY HASH(id)
PROPERTIES (...);
1 row in set (0.00 sec) -
修正後のテーブルデータをクエリします。結果は、StarRocksが修正された式に基づいて生成列
newcol1
とnewcol2
の値を再計算することを示しています。MySQL [example_db]> select * from test_tbl3;
+------+------------+------------------+---------+---------+
| id | data_array | data_json | newcol1 | newcol2 |
+------+------------+------------------+---------+---------+
| 1 | [1,2] | {"a": 1, "b": 2} | [1,2] | 2 |
+------+------------+------------------+---------+---------+
1 row in set (0.01 sec)
-