OceanBaseデータベースは、JSONデータの部分的更新(JSONパーシャルアップデート)をサポートしています。JSONドキュメント内の特定のフィールドのみを変更する場合、この機能により、JSONドキュメント全体を完全に更新することなく、変更したい部分のみを更新できます。
使用上の制限
Json Partial Updateスイッチ
OceanBaseデータベースのJson Partial Update機能は、デフォルトで無効になっています。このスイッチはシステム変数 log_row_value_options によって制御されます。詳細については、log_row_value_optionsを参照してください。
例:
Json Partial Update機能を有効にします。
- セッションレベル:
SET log_row_value_options="partial_json";- グローバルレベル:
SET GLOBAL log_row_value_options="partial_json";Json Partial Update機能を無効にします。
- セッションレベル:
SET log_row_value_options="";- グローバルレベル:
SET GLOBAL log_row_value_options="";log_row_value_optionsの値を照会します。SHOW VARIABLES LIKE 'log_row_value_options';実行結果は次のとおりです:
+-----------------------+-------+ | Variable_name | Value | +-----------------------+-------+ | log_row_value_options | | +-----------------------+-------+ 1 row in set
Partial Updateで使用できるJSON式
JSON Partial Update機能のスイッチlog_row_value_optionsに加えて、JSONドキュメントを更新するための特定の式を使用して、JSON Partial Updateをトリガーする必要があります。
現在のOceanBaseデータベースのMySQLモードでPartial Updateが可能なJSON式は以下のとおりです:
- json_setまたはjson_replace:JSONフィールドの値を更新するために使用します。
- json_remove:JSONフィールドを削除するために使用します。
注意
SET代入句の左辺の操作数とJSON式の最初のパラメータが同じであること、かつ両方ともテーブル内のJSON列であることを保証する必要があります。例えば、j = json_replace(j, '$.name', 'ab')では、等号の左側のパラメータと等号の右側のJSON式json_replaceの最初のパラメータはどちらもjです。- 現在のJSON列のデータが
outrowストレージである場合にのみ、JSON Partial Updateがトリガーされます。outrowまたはinrowストレージは、テーブル作成時のパラメータlob_inrow_thresholdによって制御されます。lob_inrow_thresholdはINROWしきい値を設定するために使用され、LOBデータサイズがこのしきい値を超えると、LOB Metaテーブル内でOUTROWストレージに変換されます。デフォルトは4KBです。
例:
テーブル
json_testを作成します。CREATE TABLE json_test(pk INT PRIMARY KEY, j JSON);データを挿入します。
INSERT INTO json_test VALUES(1, CONCAT('{"name": "John", "content": "', repeat('x',8), '"}'));実行結果は次のとおりです:
Query OK, 1 row affectedJSON列
jのデータをクエリします。SELECT j FROM json_test;実行結果は次のとおりです:
+-----------------------------------------+ | j | +-----------------------------------------+ | {"name": "John", "content": "xxxxxxxx"} | +-----------------------------------------+ 1 row in setjson_repalceを使用して、JSON列nameフィールドの値を更新します。UPDATE json_test SET j = json_replace(j, '$.name', 'ab') WHERE pk = 1;実行結果は次のとおりです:
Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0JSON列
jの変更後のデータをクエリします。SELECT j FROM json_test;実行結果は次のとおりです:
+---------------------------------------+ | j | +---------------------------------------+ | {"name": "ab", "content": "xxxxxxxx"} | +---------------------------------------+ 1 row in setjson_setを使用して、JSON列nameフィールドの値を更新します。UPDATE json_test SET j = json_set(j, '$.name', 'cd') WHERE pk = 1;実行結果は次のとおりです:
Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0JSON列
jの変更後のデータをクエリします。SELECT j FROM json_test;実行結果は次のとおりです:
+---------------------------------------+ | j | +---------------------------------------+ | {"name": "cd", "content": "xxxxxxxx"} | +---------------------------------------+ 1 row in setjson_removeを使用して、JSON列nameフィールドの値を削除します。UPDATE json_test SET j = json_remove(j, '$.name') WHERE pk = 1;実行結果は次のとおりです:
Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0JSON列
jの変更後のデータをクエリします。SELECT j FROM json_test;実行結果は次のとおりです:
+-------------------------+ | j | +-------------------------+ | {"content": "xxxxxxxx"} | +-------------------------+ 1 row in set
更新の粒度
OceanBaseデータベースでは、JSONデータはLob形式で格納されており、そのLobは基盤としてブロック単位で保存されます。そのため、パーシャル更新の際に更新されるデータ量は、少なくとも1つのLobブロック単位となります。Lobブロックが小さければ小さいほど、書き込まれるデータ量は少なくなります。このため、列作成時にLobブロックサイズを指定するDDL構文も提供されています。
例:
CREATE TABLE json_test(pk INT PRIMARY KEY, j JSON CHUNK '4k');
Chunk Sizeは無限に小さくすることはできません。小さすぎるとSELECT、INSERT、DELETEのパフォーマンスに影響します。一般的には、JSONドキュメントの平均フィールドサイズに応じて設定することを推奨します。大部分のフィールドが非常に小さい場合は、1Kに設定できます。OceanBaseデータベースはLob型データの読み取りを最適化するため、4K未満のデータについては直接INROWで保存し、この場合はパーシャル更新は行われません。パーシャル更新は主に大規模なドキュメントの更新パフォーマンスを向上させるためのものであり、小規模なドキュメントでは全量更新の方がパフォーマンスが良い場合があります。
Rebuild
Json Partial Updateは、Json列の更新前後のデータ長に制限を設けません。新しい値の長さが古い値の長さ以下の場合、元の場所のデータを新しいデータで直接置き換えます。新しい値の長さが古い値の長さを超える場合、最後尾に新しいデータを追加します。OceanBaseデータベースではしきい値を設定しており、追加されるデータの長さが元のデータ長の30%を超えた場合にRebuildを実行します。このときPartial Updateは行われず、データは完全に上書きされます。
JSON_STORAEG_SIZE式を使用してJSONの実際のストレージ長を取得し、JSON_STORAGE_FREEを使用して追加のストレージオーバーヘッドを取得できます。
例:
Json Partial Updateを有効にします。
SET log_row_value_options = "partial_json";テストテーブル
json_testを作成します。CREATE TABLE json_test(pk INT PRIMARY KEY, j JSON CHUNK '1K');テーブル
json_testに1行のデータを挿入します。INSERT INTO json_test VALUES(10 , json_object('name', 'zero', 'age', 100, 'position', 'software engineer', 'profile', repeat('x', 4096), 'like', json_array('a', 'b', 'c'), 'tags', json_array('sql boy', 'football', 'summer', 1), 'money' , json_object('RMB', 10000, 'Dollers', 20000, 'BTC', 100), 'nickname', 'noone'));実行結果は次のとおりです:
Query OK, 1 row affectedJSON_STORAGE_SIZEでJson列のストレージサイズ(実際に使用されているストレージ容量)を確認し、JSON_STORAGE_FREEでJson列から解放できるストレージ容量を推定します。SELECT JSON_STORAGE_SIZE(j), JSON_STORAGE_FREE(j) FROM json_test WHERE pk = 10;実行結果は次のとおりです:
+----------------------+----------------------+ | JSON_STORAGE_SIZE(j) | JSON_STORAGE_FREE(j) | +----------------------+----------------------+ | 4335 | 0 | +----------------------+----------------------+ 1 row in setPartial Updateが行われていないため、
JSON_STORAGE_FREEの値は0です。json_replaceを使用して、Json列positionフィールドの値を更新します。新しい値の長さは古い値の長さより短いです。UPDATE json_test SET j = json_replace(j, '$.position', 'software enginee') WHERE pk = 10;実行結果は次のとおりです:
Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0再度
JSON_STORAGE_SIZEでJson列のストレージサイズを確認し、JSON_STORAGE_FREEでJson列から解放できるストレージ容量を推定します。SELECT JSON_STORAGE_SIZE(j), JSON_STORAGE_FREE(j) FROM json_test WHERE pk = 10;実行結果は次のとおりです:
+----------------------+----------------------+ | JSON_STORAGE_SIZE(j) | JSON_STORAGE_FREE(j) | +----------------------+----------------------+ | 4335 | 1 | +----------------------+----------------------+ 1 row in setJson列データを更新した後、新しいデータが古いデータより1バイト少ないため、
JSON_STORAGE_FREEの結果は1です。json_replaceを使用して、Json列positionフィールドの値を更新します。新しい値の長さは古い値の長さより長いです。UPDATE json_test SET j = json_replace(j, '$.position', 'software engineera') WHERE pk = 10;実行結果は次のとおりです:
Query OK, 1 row affected Rows matched: 1 Changed: 1 Warnings: 0再度
JSON_STORAGE_SIZEでJson列のストレージサイズを確認し、JSON_STORAGE_FREEでJson列から解放できるストレージ容量を推定します。SELECT JSON_STORAGE_SIZE(j), JSON_STORAGE_FREE(j) FROM json_test WHERE pk = 10;実行結果は次のとおりです:
+----------------------+----------------------+ | JSON_STORAGE_SIZE(j) | JSON_STORAGE_FREE(j) | +----------------------+----------------------+ | 4355 | 19 | +----------------------+----------------------+ 1 row in setJson列データをAppend更新した後、
JSON_STORAGE_FREEの長さは19であり、Rebuild後に19バイトを解放できることを意味します。