将存档的SQL记录转换为规范化结构有什么长期影响?

时间:2014-01-08 19:45:46

标签: mysql sql ruby-on-rails optimization normalization

我的情况是我有UserProduct的表格,其格式类似于:

用户

  • id(primary,integer)
  • 名称
  • vote_count(整数)
  • 的updated_at

产品

  • id(primary,integer)
  • 名称
  • 价格(浮动)
  • 数量(整数)
  • 的updated_at

应用程序仅包含聚合计数,因此我没有构建“投票”表或“product_items”表,ergo,quantityvote_count列。

我还保留了每个模型的历史快照,类似于Ruby的paper_trail gem:

版本

  • ITEM_TYPE
  • ITEM_ID
  • created_at
  • object(text / blob)

每天都会保存每个用户和产品的快照,并将数据存储为versions内的简单blob。

现在,对于面向前端的应用和/或报告,我想做一些事情,例如绘制产品的价格和数量,随时间变化。使用versions表,我只需提取具有相应id /类型的所有条目,然后在应用程序代码中处理object blob ...即。将每个object转换为Hash并提取pricequantity字段。

好的,假设usersproducts表将包含我想要跟踪的任意数量的数字字段。档案记录的versions方式似乎效率低下。如果我想提取系统范围内的平均产品价格(SELECT AVERAGE(price) FROM PRODUCTS [join versions, extract price from :object, etc.] GROUP BY updated_at) ...我正在进行查询以获取blob,然后计算应用程序代码中的平均值。

(假装我没有使用Postgres或以其他方式使用类似HStore的系统)

为了保持一致性和性能,我正在考虑将从versions.objects封装的数据规范化为:

archived_attributes

  • ID
  • 名称

e.g。

  {id: 1, name: quantity}, {id: 2, name: price}

archived_values

  • ITEM_ID
  • ITEM_TYPE
  • archived_attribute_id(整数)
  • value(float)
  • created_at

    {item_id:1,item_type:product,archived_attribute_id:2,value:10.5,created_at:2012-10-10}

    {item_id:2,item_type:product,archived_attribute_id:2,value:14.5,created_at:2012-11-05}

我理解这需要预先管理一些应用程序逻辑,但是我可能遇到的中期问题是什么?假设archived_attributes和记录的类型数量将随意增长,甚至是快照的频率,以至于我一年内可以轻松拥有10亿archived_values。我是否正确地假设即使从1B到10B,该表的相对狭窄对于合理的MYSQL服务器也是可操作的?

1 个答案:

答案 0 :(得分:0)

我认为即使可以创建一个高级抽象来无缝地保存和检索所需聚合的属性,它最终也会变得难以超过它可能带来的任何(最小)优化优势。

愚蠢的是,这引入了Entity-Attribute-Value(名称 - 值对)模式,它在SQL级别上存在大量问题。正如SQL Antipatterns的书中所说:“这似乎是一种改进的设计。然而,简单的数据库结构并不能弥补使用它的难度。”