データのシリアライズ
要約:シリアライズされたデータをデータベースに格納しないでください。これには、カンマ区切りの値を文字列として格納することも含まれます。
Railsでは、シリアライズされたデータをJSONやYAMLなどの形式で格納することができます。このようなフィールドは次のように定義できます:
class Issue < ActiveRecord::Model
serialize :custom_fields
end
シリアライズされたデータをデータベースに格納したくなるかもしれませんが、これには多くの問題があります。このドキュメントではこれらの問題を概説し、代替案を提供します。
シリアライズされたデータは強力ではありません
リレーショナルデータベースを使用する場合、個々のフィールドをクエリしたり、スキーマを変更したり、インデックスを作成したりすることができます。シリアル化されたデータを使用する場合、そのようなことはすべて非常に困難か、まったく不可能になります。PostgreSQLはJSONフィールドをクエリする機能を提供していますが、そのほとんどは非常に特殊な使用例を想定しており、より一般的な使用には向いていません。YAMLを使用する場合、データをクエリする方法はありません。
スペースの無駄
JSON や YAML のようなシリアライズされたデータを保存することは多くのスペースを浪費することになります。これらのフォーマットは保存するデータ以外に追加文字 (たとえば、二重引用符や改行) を含むことが多いからです。
管理が難しい
シリアライズされたデータに新しいフィールドを追加したり、既存のフィールドを変更しなければならない場合があります。シリアライズされたデータを使用する場合、保存されている値をすべて書き直すしかないため、これは難しく、非常に時間がかかります。そのためには次のようなことが必要です:
- データの取得
- Ruby構造体にパースします。
- 変異させる
- 文字列へのシリアライズ
- データベースに格納
一方、通常のカラムを使用する場合、カラムを追加することは次のようになります:
ALTER TABLE table_name ADD COLUMN column_name type;
このようなクエリはほとんど時間がかからず、大きなJSONもしくはYAML構造を書き直すことなく、すべての行に適用されます。
最後に、JSON や YAML 構造がもはや十分ではなく、マイグレーションしなければならないときが来ます。数行しか保存しない場合は問題ありませんが、数百万行を保存する場合はマイグレーションに数時間から数日かかることもあります。
リレーショナルデータベースはドキュメントストアではありません
JSON や YAML としてデータを保存する場合、基本的に、データベースをドキュメントストア (たとえば MongoDB) のように使っていることになります。つまり、もったいないのです。
一貫性のあるフィールド
時々シリアライズされたデータを支持する議論として、大きく異なるフィールドや値を保存しなければならないというものがあります。このような場合、シリアライズされたデータを使用することは理にかなっているかもしれません。しかし、99%の場合、格納されるフィールドや型はどの行も同じになる傾向があります。多少の違いがあっても、別々のカラムを使用し、不要なカラムを設定しないようにすればよいのです。
解決策
解決策は、別々のカラムや別々のテーブルを使用することです。これにより、データベースが提供するすべての機能を使用できるようになり、データの管理やマイグレーションが容易になります。