# JSON 型 ## 例 ```json { "職務スキル": "Java", "プロジェクト経験": "3年以上" } ``` ```sql SELECT * FROM t1 WHERE data->"$.職務スキル" = "Java"; ``` ## JSON 型 + INDEX ```sql ALTER TABLE members ADD INDEX idx_custom_skills ((JSON_UNQUOTE(custom_choices->"$.職務スキル"))); ``` ### 検討 - パフォーマンス - 上記インデックスの利用 - 高度な集計には不向き - 対策:集計結果を非正規化キャッシュテーブルに保存しておくなど ## JSON型 + JSON_TABLE - [MySQL :: MySQL 8.4 Reference Manual :: 14.17.6 JSON Table Functions](https://dev.mysql.com/doc/refman/8.4/en/json-table-functions.html) - Extracts data from a JSON document and returns it as a relational table having the specified columns. ### データ構造例 ```sql CREATE TABLE members ( id INT PRIMARY KEY, name VARCHAR(100), custom_fields JSON ); -- サンプルデータの挿入 INSERT INTO members (id, name, custom_fields) VALUES (1, 'Alice', '{"職務スキル": "Java", "プロジェクト経験": "3年以上"}'), (2, 'Bob', '{"職務スキル": "Python", "プロジェクト経験": "1-3年"}'), (3, 'Charlie', '{"職務スキル": "Java", "プロジェクト経験": "1-3年"}'); ``` ### クロス集計 ```sql SELECT jt.職務スキル, jt.プロジェクト経験, COUNT(m.id) AS member_count FROM members AS m, JSON_TABLE( m.custom_fields, "quot; COLUMNS ( 職務スキル VARCHAR(100) PATH "$.職務スキル", プロジェクト経験 VARCHAR(100) PATH "$.プロジェクト経験" ) ) AS jt GROUP BY jt.職務スキル, jt.プロジェクト経験; ``` | 職務スキル | プロジェクト経験 | member_count | | ---------- | ---------------- | ------------ | | Java | 3年以上 | 1 | | Python | 1-3年 | 1 | | Java | 1-3年 | 1 | ### 制約 - `JSON_TABLE` で展開した列自体にはインデックスを直接適用できない - JSON データ内の特定フィールドに対しては、 `JSON_EXTRACT` などを用いて部分インデックスを作成可能 - データが増えると効果は限定的 - 更新処理には非対応 - データ量に応じてパフォーマンス低下 ## データ量 - 目安: 10 万件くらいまで - 増えても数十万件まで - 100 万件いくと厳しい - `company_id` などで先に絞り込めれば大丈夫なはず ### 先に絞り込む例 - `company_id` に INDEX が貼られていること - 絞り込んだ結果が数百件以下に収まること ```sql SELECT jt.職務スキル, jt.プロジェクト経験, COUNT(m.id) AS member_count FROM members AS m JOIN JSON_TABLE( m.custom_fields, "quot; COLUMNS ( 職務スキル VARCHAR(100) PATH "$.職務スキル", プロジェクト経験 VARCHAR(100) PATH "$.プロジェクト経験" ) ) AS jt WHERE m.company_id = 123 GROUP BY jt.職務スキル, jt.プロジェクト経験; ``` ## キャッシュテーブル [[キャッシュテーブル]] ## Validation [[JSON 型 + Validation]]