VillageSQL is a drop-in replacement for MySQL with extensions.
All examples on this page work on VillageSQL. Install Now →
JSON 列型は、挿入時に JSON を検証し、効率的にアクセスできるようバイナリ形式で格納し、ドキュメント全体を解析せずに個々のフィールドを読み書きするための一連の関数を提供します。
JSON の格納
JSON フィールドの読み取り
JSON_EXTRACT(column, path) または短縮形の -> を使います。
"Acme" です。引用符のないプレーンな文字列を得るには、->>(JSON_UNQUOTE(JSON_EXTRACT(...)) の短縮形)を使います。
$.key— オブジェクトのフィールドにアクセスします$.array[0]— インデックスで配列要素にアクセスします$.array[*]— 配列のすべての要素$.**— 再帰ワイルドカード(任意の深さのすべての値)
JSON フィールドでのフィルタリング
->> は文字列を返すため、明示的にキャストしない限り、(16 ではなく)'16' と比較するのが正しい書き方です。キャストする場合は CAST(attributes ->> '$.ram_gb' AS UNSIGNED) とします。
JSON の変更
JSON フィールドのインデックス化
JSON 列そのものに直接インデックスを作成することはできません。特定の JSON フィールドにインデックスを作成するには、生成列を作り、その列にインデックスを作成します。WHERE attributes ->> '$.brand' = 'Acme' は idx_brand を使えます。MySQL は、生成列の式がクエリ条件と一致することを認識します。
この点はMySQL のデータ型の選択でより詳しく説明しています。インデックスが必要になるほど頻繁に JSON フィールドをクエリする場合には、これが推奨されるパターンです。
JSON と正規化された列の比較
構造が本当に可変である場合(ユーザーが設定できる属性、イベントのメタデータ、サードパーティ API のペイロード)には JSON を使います。構造が固定されていて、フィールドに対してフィルタリング、結合、または集計を行う必要がある場合は、正規化された列を使います。
よくある質問
包含クエリのために JSON 配列にインデックスを作成できますか?
標準のインデックスでは直接作成できません。JSON_CONTAINS クエリでは、配列を別の子テーブルに抽出する(正規化する)か、配列を平坦化した生成列に全文インデックスを使わない限り、唯一の選択肢はフルテーブルスキャンです。高スループットの包含クエリには、正規化のほうが良い道です。
-> と ->> の違いは何ですか?
-> は JSON 値を返します(文字列は前後の引用符を含みます)。->> は引用符を外した文字列を返します。表示、連結、およびテキストを利用するあらゆる用途には、->> が適しています。ただし、等価比較は -> でも動作します。MySQL はもう一方のオペランドを先に JSON に変換するため、attributes -> '$.brand' = 'Acme' は一致します。
JSON を格納するとパフォーマンスが低下しますか?
大きな JSON ドキュメントから 1 つのフィールドを読み取るには、バイナリ構造の解析が必要です。これはテキストの解析より速いものの、ネイティブな列の読み取りより遅くなります。頻繁にアクセスするフィールドについては、生成列とインデックスのパターンによって、読み取りのパフォーマンスがネイティブな列と同等になります。トラブルシューティング
関連項目
- MySQL のデータ型の選択 — JSON と正規化された列の使い分け
- MySQL の生成列 — 仮想生成列で JSON フィールドにインデックスを作成する
- SQL からの HTTP リクエストの送信 — HTTP API のレスポンスから JSON を解析する