在ActiveRecord中存储序列化哈希与键/值数据库对象的优点/缺点?

Lan*_*ard 16 ruby sql activerecord ruby-on-rails key-value-store

如果我有几个对象,每个对象基本上都有Profile,我用来存储随机属性,有什么优点和缺点:

  1. 在列中存储序列化哈希以进行记录,与
  2. 存储一堆belong_to主要对象的键/值对象.

假设你有这样的STI记录:

class Building < ActiveRecord::Base
  has_one :profile, :as => :profilable
end
class OfficeBuilding < Building; end
class Home < Building; end
class Restaurant < Building; end
Run Code Online (Sandbox Code Playgroud)

has_one :profile

选项1.序列化哈希

class SerializedProfile < ActiveRecord::Base
  serialize :settings
end

create_table :profiles, :force => true do |t|
  t.string   :name
  t.string   :website
  t.string   :email
  t.string   :phone
  t.string   :type
  t.text     :settings
  t.integer  :profilable_id
  t.string   :profilable_type
  t.timestamp
end
Run Code Online (Sandbox Code Playgroud)

选项2.键/值存储

class KeyValueProfile < ActiveRecord::Base
  has_many :settings
end

create_table :profiles, :force => true do |t|
  t.string   :name
  t.string   :website
  t.string   :email
  t.string   :phone
  t.string   :type
  t.integer  :profilable_id
  t.string   :profilable_type
  t.timestamp
end

create_table :settings, :force => true do |t|
  t.string   :key
  t.text     :value
  t.integer  :profile_id
  t.string   :profile_type
  t.timestamp
end
Run Code Online (Sandbox Code Playgroud)

你会选哪个?

假设99%的时间我不需要按自定义搜索settings.只是想知道在性能和未来问题的可能性方面的权衡.而定制的数量settings可能在10-50之间.

我宁愿使用设置表来使用第二个选项,因为它遵循ActiveRecord面向对象的约定.但我想知道在这种情况下是否会产生过高的性能成本.

注意:我只想知道RDBMS.这将非常适合MongoDB/Redis/CouchDB /等.但我想纯粹了解SQL的优点和缺点.

ger*_*tas 12

我遇到了同样的问题,但终于做出了决定.

散列序列化选项会导致维护问题.很难查询,扩展或重构这些数据 - 任何微妙的变化都需要迁移,这意味着读取每个记录反序列化和序列化,并且取决于重构序列化异常可能发生.我尝试了二进制序列化和JSON - 第二个更容易提取和修复但仍然太麻烦.

我正在尝试使用单独的设置表 - 更容易维护.我计划使用Preferences gem,它主要用于所有抽象,以方便使用.我不确定它是否适用于Rails 3 - 它很小,所以如果需要我可以扩展它.

2013年11月更新

最近发布的Rails 4支持PostgreSQL 9.1+的强大新功能,例如动态数据集的hstorejson列类型.这篇文章介绍了Rails 4中的hstore用法.两种类型都支持索引和高级查询功能(Json与Pg 9.3).使用activerecord-postgres-hstore gem的Rails 3用户也可以使用Hstore.

我正在将项目中的一些非关键偏好表迁移到hstores.在迁移中,我只更新表定义和execute每个表一个SQL查询来移动数据.


Jos*_*ith 5

我建议只创建一个模型调用属性,并让每个需要许多的对象都有 has_many。然后你就不必搞乱序列化或任何类似的脆弱的事情。如果您使用 :join 语法,那么您不会遇到任何实际的性能问题。

将数据序列化到 RDBMS 中几乎总是不明智的。它不仅仅涉及查询,还涉及描述和迁移数据的能力(而序列化破坏了这种能力)。

class Building < ActiveRecord::Base
  has_many :attributes
end

class Attribute < ActiveRecord::Base
   belongs_to :building
end

create_table :attributes, :force => true do |t|
  t.integer :building_id
  t.string :att_name
  t.string :data
  t.timestamp
end
Run Code Online (Sandbox Code Playgroud)