Database design 如何构造实体模型来存储具有不同数据类型的任意键/值数据?
我经常遇到使用每行键/值模型而不是严格的列/字段模型将一组任意数据存储在表中的场景。问题是,我想用正确的数据类型存储值,而不是将所有内容转换为字符串。这意味着我必须选择一个具有多个可空列的表,每个数据类型一个,或者一组值表,每个数据类型一个。我也不确定是否应该使用完整的第三范式,将键分离到一个单独的表中,通过值表中的外键引用它们,或者最好保持简单,将字符串键存储在值表中,并接受字符串的重复 旧的/坏的: 此解决方案使添加附加值成为流体环境中的难题,因为表格需要定期修改 MyTable ============================ ID Key1 Key2 Key3 int int string date ---------------------------- 1 Value1 Value2 Value3 2 Value4 Value5 Value6 我的桌子 ============================ ID键1键2键3 字符串日期 ---------------------------- 1值1值2值3 2值4值5值6 单表解决方案 此解决方案允许通过单个表简化操作。查询代码仍然需要检查空值,以确定字段存储的数据类型。可能还需要一个检查约束来确保只有一个值字段包含非空数据 DataValues ============================================================= ID RecordID Key IntValue StringValue DateValue int int string int string date ------------------------------------------------------------- 1 1 Key1 Value1 NULL NULL 2 1 Key2 NULL Value2 NULL 3 1 Key3 NULL NULL Value3 4 2 Key1 Value4 NULL NULL 5 2 Key2 NULL Value5 NULL 6 2 Key3 NULL NULL Value6 数据值 ============================================================= ID记录ID键IntValue StringValue日期值 整数字符串日期 ------------------------------------------------------------- 1 1键1值1空值 2 1键2空值2空值 3 1键3空值3 4 2键1值4空值 5 2键2空值5空值 6 2键3空值6 多表解决方案 此解决方案允许对每个表进行更简洁的用途描述,尽管代码需要提前知道数据类型,因为它需要为每个数据类型查询不同的表。索引可能更简单、更有效,因为需要索引的列更少 IntegerValues =============================== ID RecordID Key Value int int string int ------------------------------- 1 1 Key1 Value1 2 2 Key1 Value4 StringValues =============================== ID RecordID Key Value int int string string ------------------------------- 1 1 Key2 Value2 2 2 Key2 Value5 DateValues =============================== ID RecordID Key Value int int string date ------------------------------- 1 1 Key3 Value3 2 2 Key3 Value6 整数值 =============================== ID记录ID键值 int字符串int ------------------------------- 1键1值1 2键1值4 字符串值 =============================== ID记录ID键值 整型字符串 ------------------------------- 1键2值2 2键2值5 日期值 =============================== ID记录ID键值 字符串日期 ------------------------------- 1键3值3 2键3值6 你如何处理这个问题?哪种解决方案更好Database design 如何构造实体模型来存储具有不同数据类型的任意键/值数据?,database-design,Database Design,我经常遇到使用每行键/值模型而不是严格的列/字段模型将一组任意数据存储在表中的场景。问题是,我想用正确的数据类型存储值,而不是将所有内容转换为字符串。这意味着我必须选择一个具有多个可空列的表,每个数据类型一个,或者一组值表,每个数据类型一个。我也不确定是否应该使用完整的第三范式,将键分离到一个单独的表中,通过值表中的外键引用它们,或者最好保持简单,将字符串键存储在值表中,并接受字符串的重复 旧的/坏的: 此解决方案使添加附加值成为流体环境中的难题,因为表格需要定期修改 MyTable =====
此外,键列应该被分离到一个单独的表中并通过外键引用,还是应该保留在值表中并在由于某种原因键名发生变化时进行批量更新?我肯定会采用多表方法,这将使查询更简单,并消除大量未使用的字段。如果希望规范化数据库,还应该将键分离到一个附加表中,但这只是首选项的问题
我能想到的唯一更好的方法是使用面向文档的数据库,如。我更喜欢将键和值放在一个表中。我现在正在构建的数据库收集简单主语/谓语/宾语短语中有关汉字的数据点;主语和谓语都是字符串,但对象可以有任何类型。表中有一些额外的结构信息(例如谓词的类型),但并不多 我的db结构的一个特点是谓词实际上被分割成几个部分键。为了了解这是如何有用的,让我们考虑一些字符的数据点。人:
人 / reading / chinese / rén
人 / reading / japanese / on / jin
人 / reading / japanese / on / nin
人 / reading / japanese / kun / hito
人 / used-in / taiwan
人 / reading / prc
人 / reading / japan
人 / meaning / chinese / english / man; person; human
人 / meaning / japanese / english / man; person; human; quantifier for people
人 / form / strokecount / 2
人 / form / strokeorder / 34
每行代表一个数据点。第一个元素是主语,最后一个元素是宾语,中间是谓语部分。谓词部分有固定数量的列(3到5列很可能就足够了,扁平比嵌套好);未使用的部件接收空值。使用此模式,很容易制定sql语句,返回关于给定字符的所有事实,或关于给定字符数的所有日语读物(on和kun),或至少13个、最多24个笔划的所有字符,依此类推:
subject predicate1 predicate2 predicate3 ob_type ob_int ob_text ob_bool
人 reading chinese text rén
人 reading japanese on text jin
人 reading japanese on text nin
人 reading japanese kun text hito
人 used-in taiwan bool true
人 reading prc bool true
人 reading japan bool true
人 meaning chinese english text man; perso...
人 meaning japanese english text man; perso...
人 form strokecount int 2
人 form strokeorder int 34
这种方法的美妙之处在于,不需要太多的思考和预先规划,您很快就可以开始将数据输入到表中。当新的事实出现时,它们在大多数情况下都会符合这一非常普遍的结构;当您发现某些谓词很笨拙时,收集有问题的记录并更新它们以携带您最喜欢的新措辞并不太困难。不再进行模式迁移。耶
更具体地说,为了回答您的问题,我考虑了是否将值放在一个单独的表中,以及是否在另一个表中实际表示谓词
这是完全可能的,但对于我的初始版本,我发现保持简单更为重要;如果在某一点上,存储所有这些重复字符串会损害存储和性能(我的意思是我的数据库中大约有70000个字符的strokecounts,因此单是按照(len('form')+len('strokecount'))*7e4==1e6
字节的顺序来拼写谓词),我相信迁移到更复杂的方法会相对容易。唉,这也意味着
0000 0001 - int
0000 0010 - float
0000 0011 - double
0000 0100 - bool
0000 0101 - string
0000 0111 - date
============================
ID Key Value DataType
int string string int
----------------------------
1 Key Value 1