Sql 动态数据库模式

Sql 动态数据库模式,sql,database-design,architecture,dynamic-data,Sql,Database Design,Architecture,Dynamic Data,为动态逻辑数据库模式提供存储的推荐体系结构是什么 澄清一下:如果一个系统需要为一个模型提供存储,而该模型的模式在生产中可能会被用户扩展或更改,那么有哪些好的技术、数据库模型或存储引擎可以实现这一点 有几种可能性可以说明: 通过动态生成的DML创建/更改数据库对象 创建具有大量稀疏物理列的表,并仅使用“覆盖”逻辑架构所需的那些列 创建一个“长、窄”表,该表将动态列值存储为行,然后需要对这些行进行数据透视,以创建一个“短、宽”行集,其中包含特定实体的所有值 使用BigTable/SimpleDB

为动态逻辑数据库模式提供存储的推荐体系结构是什么

澄清一下:如果一个系统需要为一个模型提供存储,而该模型的模式在生产中可能会被用户扩展或更改,那么有哪些好的技术、数据库模型或存储引擎可以实现这一点

有几种可能性可以说明:

  • 通过动态生成的DML创建/更改数据库对象
  • 创建具有大量稀疏物理列的表,并仅使用“覆盖”逻辑架构所需的那些列
  • 创建一个“长、窄”表,该表将动态列值存储为行,然后需要对这些行进行数据透视,以创建一个“短、宽”行集,其中包含特定实体的所有值
  • 使用BigTable/SimpleDB PropertyBag类型系统

任何基于真实世界经验的答案都将不胜感激

MSSQL中的强类型xml字段为我们提供了帮助

拥有关系数据库的全部意义在于保持数据的安全性和一致性。当您允许用户更改模式时,您的数据完整性就消失了

如果您需要存储异构数据,例如CMS场景,我建议将经过XSD验证的XML存储在一行中。当然,您会失去性能和轻松搜索功能,但这是一个很好的折衷办法


既然已经是2016年了,那就忘了XML吧!使用JSON存储非关系数据包,并使用适当类型的列作为后端。通常情况下,您不需要在包中按值进行查询,这会很慢,即使许多当代SQL数据库本机理解JSON。

听起来您真正想要的是某种“元模式”,一种能够描述用于存储实际数据的灵活模式的数据库模式。动态模式更改是敏感的,您不想搞乱它,尤其是在允许用户进行更改的情况下

您不会找到比任何其他数据库更适合此任务的数据库,因此您最好的选择是基于其他标准选择一个数据库。例如,您使用什么平台来托管数据库?应用程序是用什么语言编写的?等

为了澄清我所说的“元模式”的含义:


这是一个非常简单的例子,您可能会有一些更具体的需求(希望更容易使用),但它确实有助于说明我的观点。您应该考虑数据库架构本身在应用程序级别上是不可变的;任何结构变化都应该反映在数据中(即该模式的实例化)。

在过去,我选择了选项C——创建一个“长、窄”表,该表将动态列值存储为行,然后需要对这些行进行透视,以创建一个“短、宽”行集,其中包含特定实体的所有值。。然而,我使用的是ORM,这确实让事情变得很痛苦。我想不出在LinqToSql中你会怎么做。我想我必须创建一个哈希表来引用这些字段


@Skliwz:我猜他对允许用户创建用户定义的字段更感兴趣。

我知道问题中提到的模型在全世界的生产系统中都有使用。我工作的一所大型大学/教学机构正在使用一个相当大的。他们专门使用长窄表方法绘制由多种数据采集系统收集的数据

此外,谷歌最近通过其代码站点发布了内部数据共享协议ProtocolBuffer,作为开源。基于这种方法建模的数据库系统将非常有趣

检查以下各项:


sql已经提供了一种更改模式的方法:ALTER命令


只要有一个表列出用户不允许更改的字段,就可以为ALTER编写一个漂亮的界面。

我在一个真实的项目中使用了这些字段:

数据库由一个表和一个字段组成,该字段是一个50的数组。上面有一个“单词”索引。所有的数据都是无类型的,所以“单词索引”工作正常。数字字段表示为字符,实际排序已在客户端完成。(如果需要,每个数据类型仍然可以有几个数组字段)

逻辑表的逻辑数据架构保存在具有不同表行“类型”(第一个数组元素)的同一数据库中。它还支持使用相同的“类型”字段以写时复制样式进行简单版本控制

优点:

  • 您可以动态地重新排列和添加/删除列,无需转储/重新加载数据库。任何新的列数据都可以在零时间内设置为初始值(实际上)
  • 碎片是最小的,因为所有记录和表都是相同大小的,所以有时它提供了更好的性能
  • 所有表架构都是虚拟的。任何逻辑模式结构都是可能的(甚至是递归的或面向对象的)
  • 它适用于“写一次,读最多,不删除/标记为已删除”的数据(大多数Web应用实际上都是这样)
  • 缺点:

  • 仅使用完整单词编制索引,不使用缩写
  • 复杂的查询是可能的,但性能略有下降
  • 取决于您首选的数据库系统是否支持数组和单词索引(它是在RDBMS中实现的)
  • 关系模型只存在于程序员的头脑中(即仅在运行时)

  • 现在我想下一步可能是——在文件系统级别实现这样一个数据库。这可能相对容易。

    你的建议并不新鲜。很多人都试过。。。大多数人发现,他们追求的是“无限”的灵活性,而最终的结果是远远低于这一点。这是数据库设计中的“蟑螂汽车旅馆”——数据输入,但几乎不可能输出。尝试为任何类型的约束编写代码,并将其概念化,您将看到
    CREATE TABLE data (
        id INTEGER NOT NULL AUTO_INCREMENT,
        key VARCHAR(255),
        data TEXT,
    
        PRIMARY KEY (id)
    );
    
    select id, password from user where email_address = "xyz@xyz.com"
    
    select id, password from user where email_address = "xyz@xyz.com"
    
    select 
        parent_id, -- user id
        data -- password
    from 
        items 
    where 
        spec_id = 3 -- make sure this is a 'password' item
        and 
        parent_id in 
        ( -- get the 'user' item to which this 'password' item belongs
            select 
                id 
            from 
                items 
            where 
                spec_id = 1 -- make sure this is a 'user' item
                and 
                id in 
                ( -- fetch all item id's with the desired 'email_address' child item
                    select 
                        parent_id -- id of the parent item of the 'email_address' item
                    from 
                        items 
                    where 
                        spec_id = 2 -- make sure this is a 'email_address' item
                        and
                        data = "xyz@xyz.com" -- with the desired data value
                )
        )
    
    select 
        parent_id, 
        data 
    from 
        items 
    where 
        spec_id = (select id from specs where name = "password") 
        and 
        parent_id in (
            select 
                id 
            from 
                items 
            where 
                spec_id = (select id from specs where name = "user") 
                and 
                id in (
                    select 
                        parent_id 
                    from 
                        items 
                    where 
                        spec_id = (select id from specs where name = "email_address") 
                        and 
                        data = "xyz@xyz.com"
                )
        )
    
    <employee lastname="Li" firstname="Joe" salary="120000" id="318"/>