DatabricksにおけるJSONデータ格納形式のパフォーマンス比較:VARIANT型 vs STRING型
1. 要約
Databricksプラットフォーム上でJSONデータを保存・処理する際の最適な形式を検証したものです。従来のSTRING型と、新しく導入されたVARIANT型について、同じ条件でクエリの実行速度を比較した結果、VARIANT型がSTRING型よりもはるかに高速であることが確認されました。
結論として、「DatabricksでJSONデータを扱う場合は、STRING型の使用をやめ、VARIANT型に移行すべき」 です。VARIANT型への移行は、クエリの高速化、コンピューティングリソースの削減、ストレージコストの最適化に直接的につながる、合理的で不可欠なステップです。
2. VARIANT型が高速で効率的な理由
この大きなパフォーマンスの差は、両データ型の根本的な仕組みの違いによるものです。
2.1. STRING型:毎回すべてを解析する非効率なアプローチ
STRING型はJSONデータを単なる「長い文字列」として保存します。これは、分厚いマニュアルを毎回最初のページから読み直して必要な情報を探すような作業を、クエリのたびに行うことに相当します。
-
毎回発生する高コストな解析処理: クエリが実行されるたびに、
get_json_objectなどの関数が各行のJSON文字列をすべて解析(パース) する必要があります。これによりCPUに非常に高い負荷がかかります。 - 統計情報の欠如: データベースはSTRING型の「中身」を認識しないため、統計情報に基づく最適化(不要なデータの読み飛ばしなど)ができません。
2.2. VARIANT型:事前準備による効率的なアプローチ
一方、VARIANT型はJSONデータを単なる文字列として保存しません。これは索引(インデックス)を使って必要なページをすぐに開くような、効率的なアプローチです。
- 解析処理の事前実行: データを書き込む時点でJSONを一度だけ解析し、最適化された内部形式(バイナリ形式) で保存します。クエリ時はこの構造化されたデータに直接アクセスするため、文字列解析の負荷が完全になくなります。
- 統計情報を利用したデータ読み飛ばし: VARIANT型は、ネストされた値に関する統計情報を自動的に収集・管理します。これにより、クエリ実行時に無関係なデータファイルをまとめて読み飛ばす(プルーニング) ことができ、大規模なデータ処理においてI/O負荷を大幅に削減します。
3. 検証手順:パフォーマンス比較の方法
以下のSQLクエリを実行することで、両データ型のパフォーマンス差を具体的に計測・比較できます。
【前提条件】
- Databricks SQL Warehouseを使用。
3.1. ステップ1: テストデータとテーブルの準備
-- テスト用の元データを作成
CREATE OR REPLACE TEMPORARY VIEW raw_json_data AS
SELECT 1 AS id, '{"user": {"id": 1, "name": "Taro", "age": 32}, "items": ["pc", "mouse"]}' AS payload_str
UNION ALL
SELECT 2 AS id, '{"user": {"id": 2, "name": "Jiro", "age": 25}, "items": ["keyboard", "monitor"]}' AS payload_str
UNION ALL
SELECT 3 AS id, '{"user": {"id": 3, "name": "Saburo", "age": 40}, "items": ["webcam"]}' AS payload_str;
-- STRING型テーブルを作成
CREATE OR REPLACE TABLE json_as_string
AS SELECT id, payload_str FROM raw_json_data;
-- VARIANT型テーブルを作成 (parse_json関数で変換)
CREATE OR REPLACE TABLE json_as_variant
AS SELECT id, parse_json(payload_str) AS payload_var FROM raw_json_data;
3.2. ステップ2: パフォーマンス比較クエリの実行
-- 【遅い】STRING型テーブルに対するクエリ
SELECT id, get_json_object(payload_str, '$.user.name') AS user_name
FROM json_as_string
WHERE CAST(get_json_object(payload_str, '$.user.age') AS INT) > 30;
-- 【速い】VARIANT型テーブルに対するクエリ
SELECT
id,
payload_var:user.name
FROM
json_as_variant
WHERE
CAST(payload_var:user.age AS INT) > 30;
3.3. ステップ3: パフォーマンスの計測と比較
クエリを実行した後、Databricks SQL Warehouseの**「クエリ履歴」** 機能を使用して、実行時間やリソース消費量を詳細に比較します。
4. 検証結果:クエリプロファイルに基づく分析
上記の手順でクエリを実行した結果、以下のクエリプロファイルが得られました。これらの結果は、VARIANT型の理論上の優位性を具体的に証明しています。
図1: STRING型テーブルのクエリプロファイル

図2: VARIANT型テーブルのクエリプロファイル

4.1. パフォーマンス指標の比較
両プロファイルから主要な指標を比較すると、その差は明らかです。
| 指標 | 図1: STRING型 | 図2: VARIANT型 | 改善率 |
|---|---|---|---|
| 総実行時間 | 1秒 413ミリ秒 | 640 ミリ秒 | 約2.2倍 高速化 |
| タスクの合計時間 (CPU負荷) | 108 ミリ秒 | 62 ミリ秒 | 約43% 削減 |
| 読み込みバイト数 (I/O) | 1.26 KB | 1.11 KB | 約12% 削減 |
4.2. 結果の考察
- 総実行時間: VARIANT型はSTRING型の半分以下の時間でクエリを完了しており、ユーザーが体感する速度が大幅に向上しています。
-
タスクの合計時間: これはクラスターが実際に処理を行ったCPU時間を示します。VARIANT型でCPU時間が43%も削減されたのは、高負荷な文字列解析処理 (
get_json_object) が不要になり、負荷の低い直接アクセスに変わったためです。これがパフォーマンス向上の主な理由です。 - 読み込みバイト数: VARIANT型のバイナリ形式はデータを効率的に格納するため、ストレージから読み込むデータ量そのものが少なくなっています。これによりストレージコストとI/O負荷の両方が削減されます。
この結果は、データ量が少ないテストケースであっても、アーキテクチャの違いが明確なパフォーマンス差として現れることを示しています。データが大規模になれば、この差はさらに大きくなります。
Discussion