序列化数据
摘要:不要在数据库中存储序列化数据,而是使用单独的列和/或表。这包括将逗号分隔的值作为字符串存储。
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 结构不再足够,你必须迁移 away from it 时。当只存储少量行时,这可能不是问题,但当存储数百万行时,这样的迁移可能需要数小时甚至数天才能完成。
关系型数据库不是文档存储
将数据存储为 JSON 或 YAML 时,你实际上是在像使用文档存储(例如 MongoDB)一样使用数据库,但你没有利用典型 RDBMS 提供的任何强大功能,也没有利用典型文档存储提供的任何功能(例如索引具有可变字段的文档字段的能力)。换句话说,这是一种浪费。
字段一致性
有时支持序列化数据的论点是必须存储差异很大的字段和值。有时这确实是事实,那么使用序列化数据可能是有意义的。然而,在 99% 的情况下,存储的字段和类型对于每一行都趋于相同。即使有轻微差异,你仍然可以使用单独的列,只需不设置那些不需要的字段即可。
解决方案
解决方案是使用单独的列和/或单独的表。 这允许你使用数据库提供的所有功能,使数据的管理和迁移更容易,节省空间,你可以高效地索引数据等等。