Mysql 如何在数据库中存储具有动态属性数的数据
我有许多不同的对象,它们具有不同的属性。到目前为止,我已经将数据保存在XML文件中,可以方便地允许不断变化的属性数量。但我正试图将其移动到数据库中 您希望以什么方式存储此数据 到目前为止,我已经确定了一些策略:Mysql 如何在数据库中存储具有动态属性数的数据,mysql,database,rdbms,Mysql,Database,Rdbms,我有许多不同的对象,它们具有不同的属性。到目前为止,我已经将数据保存在XML文件中,可以方便地允许不断变化的属性数量。但我正试图将其移动到数据库中 您希望以什么方式存储此数据 到目前为止,我已经确定了一些策略: 在对象的表中有一个名为“attributes”的字段,并在其中存储序列化或json的数据 将数据存储在两个表(对象、属性)中,并使用第三个表保存关系,使其成为真正的n:m关系。非常干净的解决方案,但获取整个对象及其所有属性可能非常昂贵 识别所有对象的公共属性,并为这些属性创建对象表的字
- 在对象的表中有一个名为“attributes”的字段,并在其中存储序列化或json的数据
- 将数据存储在两个表(对象、属性)中,并使用第三个表保存关系,使其成为真正的n:m关系。非常干净的解决方案,但获取整个对象及其所有属性可能非常昂贵
- 识别所有对象的公共属性,并为这些属性创建对象表的字段。将其余属性作为序列化数据存储在另一个字段中。这比第一种策略有优势,使搜索更容易
有什么想法吗?听起来你需要的是舔舐的东西,而不是RDBMS。2d解决方案的一个变体就是两个表(假设所有属性都是单一类型的): T1:|对象数据列|对象| id| T2:|对象id |属性|名称|属性值|(前两列上的唯一索引) 当与第三种解决方案结合使用时,效率更高,例如,所有公共字段都进入T1 Sstuffing>1属性到同一个blob中是不推荐的-您不能按属性筛选,您不能有效地更新它们如果您计划搜索特定属性,将它们序列化到单个列中是个坏主意,因为您必须使用每行函数来获取信息,所以这很少能很好地扩展 我会选择你的第二选择。在属性表中有一个属性列表,在它们自己的表中有一个对象,还有一个称为对象属性的多对多关系表 例如:
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是完全可以接受的
在这种情况下,我将以相同的方式存储它,但也有一个包含原始序列化数据的列。如果使用insert/update触发器使列数据和组合数据保持同步,则不会出现任何问题。但在实际问题出现之前,你不应该担心这一点
通过使用这些触发器,您可以最大限度地减少只在数据发生更改时才执行所需的工作。通过尝试提取子列信息,您可以在每次选择时进行不必要的工作。如果您打算在稍后编辑/操作/删除属性,那么我会选择一个真正的n:m(第二个选项)。(或者尝试将其设置为2个表,其中重复相同的属性。但数据大小将很高)
如果您没有处理属性(只是捕获和显示数据),那么您可以使用一些分隔符(确保分隔符不会出现在属性值中)如果您使用的是关系数据库,那么我认为您在列出选项方面做得很好。他们各有利弊。你处于决定什么最适合你的环境的最佳位置 序列化方法可能是最快的(取决于反序列化的代码),但这意味着您将无法使用SQL查询数据。如果您说不需要使用SQL查询数据,那么我同意@longneck,也许您应该使用键/值样式的数据库而不是关系数据库 编辑-阅读更多你的评论,如果你主要关心的是速度,为什么要切换到db。当前的XML实现有什么不好的地方?我曾经实现:
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_属性
保存通常不搜索的内容(如文本描述等)
Fast属性实际上是数据库中的普通表,以提高查询效率。它们只保存某个类或其子类的实例的值。这是为了避免额外的连接
您不必使用快速表,也不必将所有数据限制在这四个表中。让我具体说明一下DVK所说的内容 假设值的类型与表的类型相同(祝您好运,我觉得您需要它): 动态属性表 ------------------------ 身份证号码 钥匙瓦查尔 有什么价值? 示例(汽车): |id |键|值| --------------------------- |1 |“制造”|“福特”| |1 |“模型”|“边缘”| |1 |“颜色”|“蓝色”| |2 |“制造”|“雪佛兰”| |2 |“模型”|“马里布”| |2 |“最大速度”|“110英里/小时”| 因此,
实体1={('Make','Ford'),('Model','Edge'),('Color','Blue')}
和,
实体2={('Make','Chevrolet'),('Model','Malibu'),('MaxSpeed','110mph')}。我假设您没有数字属性汤,但您的数据有一定的顺序 否则,RDBMS可能不是最合适的。没有SQL的东西可能工作得更好 如果对象的类型不同,通常每个类型应有一个表 特别是如果您想使用主键连接它们。如果您有产品、订单、客户等表,而不仅仅是一个对象和属性表,那么它还有助于带来秩序和理智 然后看看你的属性。如果存在的对象超过该类型类别中50%的对象,则将其作为对象表中的一列,并在不使用时使用
null
当然,任何必填项都应定义为notnull
列
剩下的,你可以
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
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' |
MainObjectTable:
mainObjectId: PRIMARY KEY
columns...
MainObjectVariant1Table:
mainObjectId: FOREIGN KEY TO MainObjectTable
variant1Columns...
MainObjectVariant2Table:
mainObjectId: FOREIGN KEY TO MainObjectTable
variant2Columns...