概要
Databricks で JSON 形式のデータをソースとして取り込む際、浮動小数点型(float
)のフィールドが整数型(long
)として推論されるケースを確認しました。
Databricks が JSON フィールドのデータ型を推論する際、値が 123
のような整数であれば long
、123.12
のように小数部を含む場合は double
として認識します。
{"id": 1, "temperature": 36.5}
root
|-- id: long (nullable = true)
|-- temperature: double (nullable = true)
しかし、システムによっては 123.0
のような値から末尾の 0
が自動的に取り除かれ、結果として 123
として送信される場合があります。下記の JavaScript 例でも同様の動作を確認できます。
const payload = {
"id": 2,
"temperature": 123.0
};
console.log(JSON.stringify(payload, null, 2));
{
"id": 2,
"temperature": 123
}
たとえば初回に 36
という値だけが到着し bigint
型でスキーマが固定された状態で、後から 36.1
が届くと取り込みに失敗し、該当レコードは _rescued_data
列へ格納されてしまいます。
この問題への対応策は主に次の 2 通りです。可能であればソース側で小数点以下を明示する方法が推奨されます。
- ソース側で小数点以下を記述する方法
- 文字列として読み取った後にデータ型を変換する方法
- 文字列として保持してビューでデータ型を変更する方法
対応方法
1. ソース側で小数点以下を記述する方法
小数部が 0 の場合でも .0
を明示して送信します。
{
"id": 2,
"temperature": 123.0
}
2. 文字列として読み取り、データ型の変更を行う方法
primitivesAsString
オプションを true
に設定して文字列として読み込み、あとから CAST
で型変換します。
出所:JSON Files - Spark 4.0.0 Documentation
出所:from_json 関数 - Azure Databricks - Databricks SQL | Microsoft Learn
LDP(旧 DLT)で CAST
を行う場合は、SchemaHints
に変換対象のカラムを指定する必要があります。指定しないと「カラムが存在しない」というエラーとなります。
schema = """
temperature STRING,
id STRING,
_corrupt_record STRING
"""
3. 文字列として保持してビューでデータ型を変更する方法
%sql
CREATE VIEW IF NOT EXISTS workspace.json_schema_01.v_from_json_test_01
AS
SELECT
*,
named_struct(
'temperature', CAST(value_by_from_json.id AS INT),
'humidity' , CAST(value_by_from_json.temperature AS DOUBLE)
) AS casted_value_by_from_json
FROM workspace.json_schema_01.from_json_test_01;
その他の検討事項
Schema(SchemaHints)の指定だけではスキーマ拡張時に不適切
Schema
や SchemaHints
だけを指定していると、スキーマ拡張を許容した場合にデータ型がソースデータに応じて推論されてしまい、意図しない型になる恐れがあります。
schema = """
id bigint,
temperature double,
_corrupt_record STRING
"""
型の拡張(Type widening)では long
から double
への自動変換は不可
ドキュメントには次のように記載されています。
タイプ変更が byte、short、int、または long から decimal または double のいずれでもない。
出所:型の拡張 | Databricks Documentation
Streaming テーブルでは手動での型の拡張(Type widening)は不可
ALTER STREAMING TABLE 文ではデータ型の変更をサポートしていないため、Streaming テーブルに対する手動での型の拡張(Type widening)は実施不可能です。
%sql
ALTER STREAMING TABLE workspace.json_schema_01.from_json_test_01
ALTER COLUMN value_by_from_json.id
TYPE float;
[UNSUPPORTED_ALTER_COLUMN_PARAMETER] Specifying TYPE with ALTER STREAMING TABLE is not supported. SQLSTATE: 0A000