このトピックでは、ApsaraDB for SelectDB でテーブルスキーマを変更する方法と、使用方法について説明します。新しいビジネス要件に合わせて ApsaraDB for SelectDB のテーブルスキーマを変更できます。
概要
次のいずれかの操作を実行することで、既存のテーブルのスキーマを変更できます。
列を作成または削除する。
列の型を変更する。
列の順序を変更する。
Bloom フィルターインデックスを作成または変更する。
ビットマップインデックスを作成または削除する。
用語
ベーステーブル:新しいテーブルはそれぞれ、作成時にベーステーブルに対応します。
rollup:rollup テーブルは、ベーステーブルまたは別の rollup テーブルから作成されます。
インデックス:マテリアライズドインデックス。rollup テーブルとベーステーブルはどちらもマテリアライズドインデックスです。
トランザクション:各インポートジョブはトランザクションです。各トランザクションは、一意の、インクリメンタルに割り当てられたトランザクション ID によって識別されます。
しくみ
スキーマ変更を実行する基本的なプロセスは、元のインデックスデータから新しいスキーマのインデックスデータを生成することです。このプロセスには、2 種類のデータの変換が含まれます。履歴データと、スキーマ変更中にインポートされるデータです。
+----------+
| Load Job | // ロードジョブ
+----+-----+
|
| Load job generates both origin and new index data // ロードジョブは元のインデックスデータと新しいインデックスデータの両方を生成します
|
| +------------------+ +---------------+
| | Origin Index | | Origin Index | // 元のインデックス
+------> New Incoming Data| | History Data | // 新しい入力データ、履歴データ
| +------------------+ +------+--------+
| |
| | Convert history data // 履歴データを変換する
| |
| +------------------+ +------v--------+
| | New Index | | New Index | // 新しいインデックス
+------> New Incoming Data| | History Data | // 新しい入力データ、履歴データ
+------------------+ +---------------+
履歴データが変換される前に、ApsaraDB for SelectDB は最新のトランザクション ID を取得し、ID が最新のトランザクション ID より小さいすべてのインポートトランザクションが完了するまで待機します。最新のトランザクション ID は分水嶺として指定されます。ApsaraDB for SelectDB は、分水嶺トランザクション ID の後に処理されるすべてのインポートジョブが、元のインデックスと新しいインデックスの両方のデータを同時に生成することを保証します。このようにして、ApsaraDB for SelectDB は、履歴データが変換された後に新しいインデックスに完全なデータが含まれることを保証します。
スキーマ変更ジョブの作成
既存のテーブルのスキーマを変更するには、次のステートメントを実行します。スキーマ変更は非同期操作です。スキーマ変更ジョブが送信されると、送信の確認が返されます。その後、SHOW ALTER
ステートメントを実行して、ジョブの進捗状況をクエリできます。
構文
ALTER TABLE [database.]table <alter_clause>;
テーブルごとに一度に実行できるスキーマ変更ジョブは 1 つだけです。
テーブルのスキーマ変更中は、テーブルにデータをインポートしたり、テーブルからデータをクエリしたりできます。
テーブルのスキーマを変更する場合、テーブルのパーティションキー列またはバケット列を変更することはできません。
テーブルのスキーマに REPLACE メソッドを使用して集計される値列が含まれている場合、キー列を削除することはできません。
キー列を削除すると、ApsaraDB for SelectDB は REPLACE メソッドを使用して集計される値列の値を判断できません。
UNIQUE KEY モデルを使用するテーブルのキー以外のすべての列は、REPLACE メソッドを使用して集計されます。
SUM または REPLACE メソッドを使用して集計される値列をテーブルに追加する場合、値列のデフォルト値は履歴データには意味がありません。
履歴データは詳細情報が失われているため、デフォルト値は実際の集計値を表していません。
列の型を変更する場合、型以外のすべての元の属性を保持する必要があります。
たとえば、
k1 INT SUM NULL DEFAULT "1"
列の型を BIGINT に変更するには、次のステートメントを実行します。ALTER TABLE tbl1 MODIFY COLUMN k1 BIGINT SUM NULL DEFAULT "1";
新しい列の型を除いて、集計方法、NULL 値の許容、デフォルト値などの他のすべての属性は、列の元の情報を反映している必要があります。
列名、集計方法、NULL 値の許容、デフォルト値、または列コメントを変更することはできません。
<alter_clause> 句を使用して、次のいずれかの方法でスキーマ変更操作を実行できます。
指定されたインデックスの指定された位置に列を挿入します。
ADD COLUMN column_name column_type [KEY | agg_type] [DEFAULT "default_Value"] [AFTER column_name|FIRST] [TO rollup_index_name] [PROPERTIES ("key"="Value", ...)]
説明AGGREGATE KEY モデルを使用するインデックスに値列を挿入する場合、
agg_type
パラメーターを指定する必要があります。DUPLICATE KEY モデルなどの非集計モデルを使用するインデックスにキー列を挿入する場合、
KEY
キーワードを指定する必要があります。ベースインデックスに既に存在する列を rollup インデックスに挿入することはできません。ベースインデックスに既に存在する列を rollup インデックスに挿入する必要がある場合は、新しい rollup インデックスを作成できます。
指定されたインデックスに複数の列を挿入します。
ADD COLUMN (column_name1 column_type [KEY | agg_type] DEFAULT "default_Value", ...) [TO rollup_index_name] [PROPERTIES ("key"="Value", ...)]
説明AGGREGATE KEY モデルを使用するインデックスに複数の値列を挿入する場合、
agg_type
パラメーターを指定する必要があります。AGGREGATE KEY モデルを使用するインデックスに複数のキー列を挿入する場合、
KEY
キーワードを指定する必要があります。ベースインデックスに既に存在する列を rollup インデックスに挿入することはできません。ベースインデックスに既に存在する列を rollup インデックスに挿入する必要がある場合は、新しい rollup インデックスを作成できます。
指定されたインデックスから列を削除します。
DROP COLUMN column_name[FROM rollup_index_name]
説明パーティションキー列は削除できません。
ベースインデックスから列を削除すると、その列を含む rollup インデックスからも列が削除されます。
列の型を変更し、指定されたインデックスで列の位置を指定します。
MODIFY COLUMN column_name column_type [KEY | agg_type] [NULL | NOT NULL] [DEFAULT "default_Value"] [AFTER column_name|FIRST] [FROM rollup_index_name] [PROPERTIES ("key"="Value", ...)]
説明AGGREGATE KEY モデルを使用するインデックスで値列を変更する場合、
agg_type
パラメーターを指定する必要があります。非集計モデルを使用するインデックスでキー列を変更する場合、
KEY
キーワードを指定する必要があります。列の型のみを変更できます。列の他のすべての属性は、MODIFY COLUMN ステートメントの元の列属性と一致している必要があります。 詳細については、このトピックの例セクションを参照してください。
パーティションキー列またはバケット列を変更することはできません。
次の型の変換がサポートされています。 変換によって許容できない精度の損失が発生しないようにしてください。
TINYINT、SMALLINT、INT、BIGINT、LARGEINT、FLOAT、または DOUBLE 型の列を、より広い範囲の数値型に変換します。
TINTINT、SMALLINT、INT、BIGINT、LARGEINT、FLOAT、DOUBLE、または DECIMAL 型の列を VARCHAR 型に変換します。
VARCHAR 型の列の最大長を変更します。
VARCHAR または CHAR 型の列を TINTINT、SMALLINT、INT、BIGINT、LARGEINT、FLOAT、または DOUBLE 型に変換します。
VARCHAR または CHAR 型の列を DATE 型に変換します。次の日付形式がサポートされています:%Y-%m-%d、%y-%m-%d、%Y%m%d、%y%m%d、%Y/%m/%d、および %y/%m/%d。
DATETIME 型の列を DATE 型に変換します。年、月、日の情報のみが保持されます。たとえば、
2019-12-09 21:47:05
は2019-12-09
に変換されます。DATE 型の列を DATETIME 型に変換します。時、分、秒は自動的に 0 で埋められます。たとえば、
2019-12-09
は2019-12-09 00:00:00
に変換されます。FLOAT 型の列を DOUBLE 型に変換します。
INT 型の列を DATE 型に変換します。INT データの形式が無効な場合、変換は失敗します。この場合、元の列データは変更されません。
DATE 型と DATETIME 型以外のすべての型の列を STRING 型に変換できます。ただし、STRING 型の列を別の型に変換することはできません。
指定されたインデックスの列を並べ替えます。
ORDER BY (column_name1, column_name2, ...) [FROM rollup_index_name] [PROPERTIES ("key"="Value", ...)]
説明インデックス内のすべての列を指定する必要があります。
値列はキー列の後に続きます。
例
非集計モデルを使用する
example_db.my_table
テーブルのスキーマを変更します。example_rollup_index
テーブルのcol1
列の後にnew_col
という名前のキー列を挿入します。ALTER TABLE example_db.my_table ADD COLUMN new_col INT KEY DEFAULT "0" AFTER col1 TO example_rollup_index;
非集計モデルを使用する
example_db.my_table
テーブルのスキーマを変更します。example_rollup_index
テーブルのcol1
列の後にnew_col
という名前の値列を挿入します。ALTER TABLE example_db.my_table ADD COLUMN new_col INT DEFAULT "0" AFTER col1 TO example_rollup_index;
AGGREGATE KEY モデルを使用する
example_db.my_table
テーブルのスキーマを変更します。example_rollup_index
テーブルのcol1
列の後にnew_col
という名前のキー列を挿入します。ALTER TABLE example_db.my_table ADD COLUMN new_col INT DEFAULT "0" AFTER col1 TO example_rollup_index;
AGGREGATE KEY モデルを使用する
example_db.my_table
テーブルのスキーマを変更します。example_rollup_index
テーブルのcol1
列の後に、new_col
という名前で SUM 集計メソッドを使用する値列を挿入します。ALTER TABLE example_db.my_table ADD COLUMN new_col INT SUM DEFAULT "0" AFTER col1 TO example_rollup_index;
AGGREGATE KEY モデルを使用する
example_db.my_table
テーブルのスキーマを変更します。example_rollup_index
テーブルに 2 つの列を挿入します。1 つはcol1
という名前のキー列で、もう 1 つはcol2
という名前で SUM 集計メソッドを使用する値列です。ALTER TABLE example_db.my_table ADD COLUMN (col1 INT DEFAULT "1", col2 FLOAT SUM DEFAULT "2.3") TO example_rollup_index;
example_db.my_table
テーブルのスキーマを変更します。から列を削除しますexample_rollup_index
テーブルから列を削除します。ALTER TABLE example_db.my_table DROP COLUMN col2 FROM example_rollup_index;
example_db.my_table
テーブルのスキーマを変更します。ベースインデックスのcol1
という名前のキー列の型をBIGINT
に変更し、col2
列の後に移動します。ALTER TABLE example_db.my_table MODIFY COLUMN col1 BIGINT KEY DEFAULT "1" AFTER col2;
説明キー列または値列を変更する場合、列に関する完全な情報を宣言する必要があります。
example_db.my_table
テーブルのスキーマを変更します。ベースインデックスのval1
列の最大長をVARCHAR(32)
からVARCHAR(64)
に変更します。ALTER TABLE example_db.my_table MODIFY COLUMN val1 VARCHAR(64) REPLACE DEFAULT "abc";
example_db.my_table
テーブルのスキーマを変更します。内の列を並べ替えますexample_rollup_index
テーブルの列を並べ替えます。この例では、元の列の順序は k1、k2、k3、v1、v2 です。ALTER TABLE example_db.my_table ORDER BY (k3,k1,k2,v2,v1) FROM example_rollup_index;
DUPLICATE KEY モデルを使用するテーブルのキー列のフィールドの最大長を変更します。
次のサンプルコードは、元のスキーマの例を示しています。
+-----------+-------+-------------+------+------+---------+-------+ | IndexName | Field | Type | Null | Key | Default | Extra | // インデックス名、フィールド、型、NULL、キー、デフォルト、追加 +-----------+-------+-------------+------+------+---------+-------+ | tbl1 | k1 | INT | No | true | N/A | | | | k2 | INT | No | true | N/A | | | | k3 | varchar(20) | No | true | N/A | | | | k4 | INT | No | false| N/A | | +-----------+-------+-------------+------+------+---------+-------+
次のステートメントを実行して、
k3
列の最大長を 50 に変更します。ALTER TABLE example_tbl MODIFY COLUMN k3 varchar(50) key null COMMENT 'to 50'
次のサンプルコードは、変更後の新しいスキーマを示しています。
+-----------+-------+-------------+------+------+---------+-------+ | IndexName | Field | Type | Null | Key | Default | Extra | // インデックス名、フィールド、型、NULL、キー、デフォルト、追加 +-----------+-------+-------------+------+------+---------+-------+ | tbl1 | k1 | INT | No | true | N/A | | | | k2 | INT | No | true | N/A | | | | k3 | varchar(50) | No | true | N/A | | | | k4 | INT | No | false| N/A | | +-----------+-------+-------------+------+------+---------+-------+
スキーマ変更は非同期操作です。テーブルごとに一度に実行できるスキーマ変更ジョブは 1 つだけです。
スキーマ変更ジョブで複数の rollup テーブルを変更します。
次のサンプルコードは、元のスキーマの例を示しています。
+-----------+-------+------+------+------+---------+-------+ | IndexName | Field | Type | Null | Key | Default | Extra | // インデックス名、フィールド、型、NULL、キー、デフォルト、追加 +-----------+-------+------+------+------+---------+-------+ | tbl1 | k1 | INT | No | true | N/A | | | | k2 | INT | No | true | N/A | | | | k3 | INT | No | true | N/A | | | | | | | | | | | rollup2 | k2 | INT | No | true | N/A | | | | | | | | | | | rollup1 | k1 | INT | No | true | N/A | | | | k2 | INT | No | true | N/A | | +-----------+-------+------+------+------+---------+-------+
次のステートメントを実行して、
k4k4
ロールアップ 1
列をrollup1k5
テーブルに挿入し、rollup2
k4ALTER TABLE tbl1 ADD COLUMN k4 INT default "1" to rollup1, ADD COLUMN k4 INT default "1" to rollup2, ADD COLUMN k5 INT default "1" to rollup2;
次のサンプルコードは、変更後の新しいスキーマを示しています。
+-----------+-------+------+------+------+---------+-------+ | IndexName | Field | Type | Null | Key | Default | Extra | // インデックス名、フィールド、型、NULL、キー、デフォルト、追加 +-----------+-------+------+------+------+---------+-------+ | tbl1 | k1 | INT | No | true | N/A | | | | k2 | INT | No | true | N/A | | | | k3 | INT | No | true | N/A | | | | k4 | INT | No | true | 1 | | | | k5 | INT | No | true | 1 | | | | | | | | | | | rollup2 | k2 | INT | No | true | N/A | | | | k4 | INT | No | true | 1 | | | | k5 | INT | No | true | 1 | | | | | | | | | | | rollup1 | k1 | INT | No | true | N/A | | | | k2 | INT | No | true | N/A | | | | k4 | INT | No | true | 1 | | +-----------+-------+------+------+------+---------+-------+
k4 列と
k5
列もtbl1
という名前のベーステーブルに挿入されます。これは、rollup テーブルに挿入された列がベーステーブルにも自動的に挿入されることを意味します。ベーステーブルに既に存在する列を rollup テーブルに挿入することはできません。ベーステーブルに既に存在する列を rollup テーブルに挿入するには、新しい rollup テーブルを作成してから、元の rollup テーブルを削除します。
スキーマ変更ジョブのクエリ
SHOW ALTER TABLE COLUMN ステートメントを実行して、実行中または完了したスキーマ変更ジョブをクエリできます。スキーマ変更ジョブに複数のインデックスが関係している場合、ステートメントを実行すると複数の行が返されます。各行はインデックスに対応しています。
構文
SHOW ALTER TABLE COLUMN;
サンプルコード
SHOW ALTER TABLE COLUMN\G;
*************************** 1. row ***************************
JobId: 20021 // ジョブID
TableName: tbl1 // テーブル名
CreateTime: 2019-08-05 23:03:13 // 作成時間
FinishTime: 2019-08-05 23:03:42 // 終了時間
IndexName: tbl1 // インデックス名
IndexId: 20022 // インデックスID
OriginIndexId: 20017 // 元のインデックスID
SchemaVersion: 2:792557838 // スキーマバージョン
TransactionId: 10023 // トランザクションID
State: FINISHED // 状態
Msg: // メッセージ
Progress: NULL // 進捗状況
Timeout: 86400 // タイムアウト
1 row in set (0.00 sec)
次の表にパラメーターを示します。
パラメーター | 説明 |
ジョブ ID | スキーマ変更ジョブの一意の ID です。 |
TableName | スキーマ変更が実行されるベーステーブルの名前。 |
JobId | スキーマ変更ジョブの一意の ID。 |
TableName | スキーマ変更が実行されるベーステーブルの名前。 |
CreateTime | スキーマ変更ジョブが作成された時刻。 |
FinishedTime | スキーマ変更ジョブが完了した時刻。スキーマ変更ジョブが完了していない場合は、N/A が返されます。 |
IndexName | スキーマ変更に関係するインデックスの名前。 |
IndexId | 新しいインデックスの一意の ID。 |
OriginIndexId | スキーマ変更ジョブの状態です。 有効な値:
|
SchemaVersion | スキーマ変更のバージョン。M:N 形式で表示されます。M はスキーマ変更のバージョンを示し、N はバージョンのハッシュ値を示します。バージョンはスキーマ変更ごとに増加します。 |
TransactionId | 履歴データ変換の分岐点となるトランザクション ID。 |
State | スキーマ変更ジョブの状態。 有効な値: |
スキーマ変更ジョブのキャンセル
CANCEL ALTER TABLE COLUMN ステートメントを実行して、ジョブが FINISHED または CANCELLED 状態ではない場合にスキーマ変更ジョブをキャンセルできます。
構文
CANCEL ALTER TABLE COLUMN FROM <tbl_name>;
パラメーター
パラメーター | 説明 |
tbl_name | テーブルの名前。 |
例
example_db.my_table
テーブルで実行される ALTER COLUMN 操作をキャンセルします。
CANCEL ALTER TABLE COLUMNFROM example_db.my_table;
関連設定
フロントエンド設定
alter_table_timeout_second
:スキーマ変更ジョブのデフォルトのタイムアウト期間。デフォルト値:86400。単位:秒。
バックエンド設定
alter_tablet_worker_count
:バックエンドで履歴データを変換するために使用されるスレッドの数。デフォルト値:3。スキーマ変更ジョブを高速化するには、このパラメーターに大きい値を指定してバックエンドを再起動します。ただし、バックエンドで履歴データの変換に使用されるスレッドの数が多いほど、I/O 負荷が増加し、他の操作に影響を与える可能性があります。スレッドは rollup ジョブと共有されます。alter_index_worker_count
:バックエンドで履歴データのインデックスを作成するために使用されるスレッドの数。デフォルト値:3。スキーマ変更ジョブを高速化するには、このパラメーターに大きい値を指定してバックエンドを再起動します。ただし、バックエンドで履歴データのインデックス作成に使用されるスレッドの数が多いほど、I/O 負荷が増加し、他の操作に影響を与える可能性があります。説明このパラメーターは、転置インデックスのみをサポートします。
FAQ
Q:スキーマ変更ジョブの実行速度は?
A:スキーマ変更ジョブの実行速度は、最悪の効率に基づいて約 10 MB/s と推定されます。実行速度に基づいて、スキーマ変更ジョブのタイムアウト期間を指定できます。
Q:スキーマ変更ジョブを送信したときに
Table xxx is not stable. ...
エラーが報告された場合はどうすればよいですか?A:テーブルのデータが完全でバランスが取れている場合にのみ、テーブルでスキーマ変更操作を実行できます。テーブルの一部のデータシャードレプリカが不完全である場合、または一部のレプリカでバランシング操作が実行されている場合、システムはスキーマ変更ジョブを送信するリクエストを拒否します。
次のステートメントを実行して、データシャードレプリカが完全かどうかを確認できます。
ADMIN SHOW REPLICA STATUS FROM tbl WHERE STATUS != "OK";
結果が返された場合、レプリカに問題があります。ほとんどの場合、システムはこれらの問題を自動的に修正します。次のステートメントを実行して、このテーブルを修正することもできます。
ADMIN REPAIR TABLE tbl1;
または、次のステートメントを実行して、1 つ以上のバランシング操作が実行されているかどうかを確認できます。
SHOW PROC "/cluster_balance/pending_tablets";
バランシング操作が完了するまで待機するか、次のステートメントを実行してバランシング操作を一時的に無効にすることができます。
ADMIN SET FRONTEND CONFIG ("disable_balance" = "true");