我正在使用PHP和PostgreSQL重建应用程序(这里是单独的开发人员)。对于大多数数据,我使用每个属性有多列的表来存储它。但是,我现在开始为内容存储构建一些表。在这种情况下,内容是多个部分,每个部分包含不同的数据集;一些数据是常见的和共享的(和外键)和其他数据是非常独特的。在应用程序的当前迭代中,我们有一个像这样的表结构:
id | project_name | project_owner | site | customer_name | last_updated
-----------------------------------------------------------------------
1 | test1 | some guy | 12 | some company | 1/2/2012
2 | test2 | another guy | 04 | another co | 2/22/2012
现在,这有效 - 但由于一些原因,它很难维护。添加新列(很少发生)需要修改数据库表。审计/历史记录跟踪需要一个单独的表,该表使用附加信息镜像主表 - 如果更改主表,还需要修改。最后,有很多专栏 - 在某些表格中超过100个。
我一直在集思广益,包括将一张大桌分成几个较小的桌子。这引入了我认为也会引起问题的其他问题。
我目前正在考虑的方法似乎被称为EAV模型。我有一张看起来像这样的表:
id | project_name | col_name | data_varchar | data_int | data_timestamp | update_time
--------------------------------------------------------------------------------------------------
1 | test1 | site | | 12 | | 1/2/2012
2 | test1 | customer_name | some company | | | 1/2/2012
3 | test1 | project_owner | some guy | | | 1/2/2012
......等等。这样做的好处是我永远不会更新,总是插入。数据永远不会被覆盖,只会添加。当然,这张桌子最终会变得相当大。我有一个列表项目的“索引”表,用于引用“数据”表。但是我觉得我错过了这种方法。它会扩展吗?我本来想做一个简单的密钥 - >值类型表,但意识到我需要能够在表中具有不同的数据类型。这似乎是可管理的,因为我正在使用的数据库抽象层将包含一个从正确的列中选择数据的类型。
我为自己做了太多的工作吗?我应该坚持使用带有大量色谱柱的简单桌子吗?
答案 0 :(得分:3)
我的建议是,如果您可以避免使用EAV表,请执行此操作。他们往往是性能杀手。它们也难以正确查询,特别是报告(是的,让我加入这个表未知的次数,以获取我需要的所有数据,哦顺便说一句,我不知道我有哪些列所以我不知道报告需要包含哪些列)并且很难获得确保数据完整性所需的数据库约束(例如,如何确保填写必填字段)并且它可能导致你使用糟糕的数据类型。从长远来看,定义存储所需数据的表会好得多。
如果您真的需要这些功能,那么至少要研究NoSQL数据库,这些数据库针对这种未定义的数据进行了更优化。
答案 1 :(得分:0)
将整个结构移动到EAV可能会导致很多问题,但是对于问题的审计跟踪部分可能是可以接受的,因为通常外键关系和严格的数据类型可能会无论如何,随着时间消失。您甚至可以使用触发器和存储过程自动生成审计表。
但是,请注意,重建旧版本的记录对于EAV审计跟踪来说并不重要,并且需要相当数量的应用程序代码。数据库将无法单独完成。
您可以考虑的另一种方法是将所有数据(新旧记录)存储在相同的表中。您可以在同一个表中包含审计字段,并在不必要时保留NULL,或者将表中的某些行存储为“当前”,并将审计相关字段存储在另一个表中。要简化应用程序,您可以创建一个仅显示当前行的视图,并针对视图发出查询。
您可以使用联接表继承模式完成此操作。使用连接表继承,可以将公共属性与“类型”列一起放入基表,并且可以根据类型连接到其他表(具有相同的主键,也是外键)。许多Data-Mapper-Pattern ORM都支持这种模式,通常称为“多态”。
您也可以使用PostgreSQL的原生table inheritance mechanism,但请注意注意事项!