🐙
json型のデメリット
Daily Blogging84日目
RDBのjson型はスキーマレスに使えて色々便利に見えるけど、ちゃんとデメリットもあるので注意が必要
json型のデメリット
ざっくりこんな感じのデメリットがある
- 古いバージョンのORMはそもそもサポートしてないケースが多い
- 検索時のクエリが複雑になる
- 整合性が取れない
- 型指定ができない
古いバージョンのORMはそもそもサポートしてないケースが多い
最新のバージョンであればjson型やjsonb型をサポートしているORMも多いが、
バージョンが古いとサポートされていないことが多い
サポートされていない場合、jsonデータを登録/更新/検索する操作がさらに難しくなる
検索時のクエリが複雑になる
ORMがjson型をサポートしていたとしても、クエリが通常よりも複雑になりがち
↓ActiveRecordの場合
# cityというキーに紐づく値がTokyoのレコードを取得するクエリ
User.where("profile->>'city' = ?", "Tokyo")
jsonデータがネストしている場合、もっと見づらい
User.where("profile->'address'->>'zipcode' = ?", "12345")
曖昧検索したいなら
User.where("profile->'skills' @> ?", '["Ruby"]')
検索条件が複雑になるともっとクエリも複雑になるよ
json型の場合、インデックスも適用されない
※jsonb型ならGinインデックスが使える
整合性が取れない
外部キー制約もユニーク制約も適応できないので、不正な値が入る可能性が高い。
CHECK制約で、特定の属性を必須にすることは可能
でも制約の変更が面倒臭い
jsonb型の場合
jsonb_exists関数が使える
ALTER TABLE users ADD CONSTRAINT check_profile_has_age
CHECK (jsonb_exists(profile, 'age'));
json型の場合
やや面倒くさい
ALTER TABLE users ADD CONSTRAINT check_profile_has_age
CHECK ((profile->'age') IS NOT NULL);
必須属性を増やす場合
-- 一回制約をドロップして
ALTER TABLE users DROP CONSTRAINT check_profile_age;
-- 新しく作り直す必要がある
ALTER TABLE users ADD CONSTRAINT check_profile_age_and_address
CHECK (
profile->'age' IS NOT NULL AND
json_typeof(profile->'age') = 'number' AND
profile->'address' IS NOT NULL
);
型指定ができない
値の型を指定できないので、同じ意味合いの値でもフォーマットが異なる可能性がある。
日付の場合
yyyy-mm-dd
yyyy/mm/dd
とか表記触れが発生することも
json型の使い所
上記のデメリットが適用されない時になら使ってもそんな支障ない
Discussion