我有许多具有不同数量属性的不同对象。到目前为止,我已将数据保存在XML文件中,这些文件可轻松实现不断变化的属性数量。但我正试图将其移至数据库。
存储此数据的首选方式是什么?
到目前为止我已经确定了一些策略:
有什么想法吗?
答案 0 :(得分:22)
如果您曾计划搜索特定属性,那么将它们序列化为单个列是一个坏主意,因为您必须使用每行函数来获取信息 - 这很少能很好地扩展。
我会选择你的第二选择。拥有属性表中的属性列表,自己表中的对象以及称为对象属性的多对多关系表。
例如:
objects:
object_id integer
object_name varchar(20)
primary key (object_id)
attributes:
attr_id integer
attr_name varchar(20)
primary key (attr_id)
object_attributes:
object_id integer references (objects.object_id)
attr_id integer references (attributes.attr_id)
oa_value varchar(20)
primary key (object_id,attr_id)
您注意到对性能的关注,但根据我的经验,拆分列的成本总是比组合多列更昂贵。如果事实证明存在性能问题,那么出于性能原因打破3NF是完全可以接受的。
在这种情况下,我会以相同的方式存储它,但也有一个包含原始序列化数据的列。如果使用插入/更新触发器来保持列式和组合数据同步,则不会出现任何问题。但是,在实际出现问题之前,你不应该担心这一点。
通过使用这些触发器,您可以最大限度地减少数据更改时 所需的工作量。通过尝试提取子列信息,您可以对每个选择进行不必要的工作。
答案 1 :(得分:6)
2d解决方案的变体只是两个表(假设所有属性都是单一类型):
T1:|对象数据列| Object_id |
T2:| Object id | attribute_name | attribute value | (前2列的唯一索引)
与第3种解决方案结合使用时效率更高,例如所有常见字段都进入T1。
不建议将Sstuffing> 1属性放入同一个blob中 - 您无法按属性过滤,无法有效更新它们
答案 2 :(得分:3)
让我对DVK所说的内容给出一些具体的解释。
假设值的类型相同,表格看起来就像(祝你好运,我觉得你需要它):
dynamic_attribute_table ------------------------ id NUMBER key VARCHAR value SOMETYPE?
示例(汽车):
|id| key | value | --------------------------- | 1|'Make' |'Ford' | | 1|'Model' |'Edge' | | 1|'Color' |'Blue' | | 2|'Make' |'Chevrolet'| | 2|'Model' |'Malibu' | | 2|'MaxSpeed'|'110mph' |
因此,
实体1 = {('Make','Ford'),('Model','Edge'),('Color','Blue')}
并且,
实体2 = {('Make','Chevrolet'),('Model','Malibu'),('MaxSpeed','110mph')}。
答案 3 :(得分:2)
如果您使用的是关系数据库,那么我认为您在列出选项方面做得很好。他们各有利弊。你最有能力决定什么最适合你的情况。
序列化方法可能是最快的(取决于您的反序列化代码),但这意味着您将无法使用SQL查询数据。如果你说你不需要用SQL查询数据,那么我同意@longneck,也许你应该使用键/值样式db而不是关系数据库。
编辑 - 阅读更多评论,如果速度是您的主要考虑因素,您为什么要切换到数据库。关于您当前的XML实现有什么不好?
答案 4 :(得分:2)
我曾经实施this scheme:
t_class (id RAW(16), parent RAW(16)) -- holds class hierachy.
t_property (class RAW(16), property VARCHAR) -- holds class members.
t_declaration (id RAW(16), class RAW(16)) -- hold GUIDs and types of all class instances
t_instance (id RAW(16), class RAW(16), property VARCHAR2(100), textvalue VARCHAR2(200), intvalue INT, doublevalue DOUBLE, datevalue DATE) -- holds 'common' properties
t_class1 (id RAW(16), amount DOUBLE, source RAW(16), destination RAW(16)) -- holds 'fast' properties for class1.
t_class2 (id RAW(16), comment VARCHAR2(200)) -- holds 'fast' properties for class2
--- etc.
RAW(16)
是Oracle
拥有GUID
s
如果要选择对象的所有属性,请发出:
SELECT i.*
FROM (
SELECT id
FROM t_class
START WITH
id = (SELECT class FROM t_declaration WHERE id = :object_id)
CONNECT BY
parent = PRIOR id
) c
JOIN property p
ON p.class = c.id
LEFT JOIN
t_instance i
ON i.id = :object_id
AND i.class = p.class
AND i.property = p.property
t_property
保存您通常不会搜索的内容(例如,文字说明等)。
快速属性实际上是数据库中的普通表,以提高查询效率。它们仅为某个类或其后代的实例保存值。这是为了避免额外的连接。
您不必使用快速表并将所有数据限制在这四个表中。
答案 5 :(得分:1)
听起来你需要点击couchdb,而不是RDBMS。
答案 6 :(得分:1)
如果您要在稍后的时间点编辑/操作/删除属性,那么制作一个真正的n:m(第二个选项)就是我要去的那个。 (或者尝试将其设为2表,其中相同的属性重复。但数据大小会很高)
如果您没有处理属性(只捕获和显示数据),那么您可以继续使用一些分隔符存储在一个字段中(确保分隔符不会出现在属性值中)
答案 7 :(得分:0)
我假设您没有数字属性汤,但是您的数据有一定顺序。
否则,RDBMS可能不是最合适的。没有SQL的地方可能会更好。
如果您的对象属于不同类型,则通常每种类型应有一个表。
特别是如果要使用主键进行连接。如果您具有“产品”,“订单”,“客户”等表,而不仅仅是“对象和属性”表,则还有助于带来订单和理智。
然后查看您的属性。对于该类型类别中50%的对象,存在的所有内容都超过该对象,则将其设置为对象表中的一列,并在不使用时使用null
。
任何强制性的内容,当然都应定义为NOT NULL
列。
其余的,您可以具有一个或几个“额外属性”表。
您可以将属性名称和值一起放入表中,或将它们规范化到单独的表中,而仅在值表中使用主键。
您可能还会发现您有数据组合。例如,一种对象类型的变体始终具有一组特定的属性,而同一对象类型的另一种变体具有另一组属性。
在这种情况下,您可能想要执行以下操作:
MainObjectTable:
mainObjectId: PRIMARY KEY
columns...
MainObjectVariant1Table:
mainObjectId: FOREIGN KEY TO MainObjectTable
variant1Columns...
MainObjectVariant2Table:
mainObjectId: FOREIGN KEY TO MainObjectTable
variant2Columns...
我认为,从长远来看,将获得回报的艰巨工作是分析数据,找到对象和常用属性,并使之成为一个好的“对象/ ERD / DB”模型。