热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【问】如何应对关系型数据库中列的不断增加

光看文章的题目可能很难明白我想说什么,还是先描述一下项目中遇到的问题吧。我们项目中一张这样的表用来保存各种资源,假设为资源1、资源2等等,用ResGenre来标识。我们可以认为资源类型是一个抽象的概念,资源1、资源2这些都是资源子类。一开始所有

光看文章的题目可能很难明白我想说什么,还是先描述一下项目中遇到的问题吧。 我们项目中一张这样的表用来保存各种资源,假设为资源1、资源2等等,用ResGenre来标识。 我们可以认为 资源类型 是一个抽象的概念,资源1、资源2这些都是 资源子类 。一开始所有

光看文章的题目可能很难明白我想说什么,还是先描述一下项目中遇到的问题吧。

我们项目中一张这样的表用来保存各种“资源”,假设为资源1、资源2……等等,用ResGenre来标识。

我们可以认为资源类型是一个抽象的概念,资源1、资源2这些都是资源子类。一开始所有这些子类型都只有ResId,ResName等几个字段,一张ResInfo表就可以满足需求了。但是我们都知道项目千变万化,唯一不变的就是“变化”。随着业务的发展可能资源子类型越来越多,头疼的是原来的这张表的几个字段已经满足不了需求了,各个子类型的字段在不断扩充,最头疼的是它们加的字段都各不相同……这时该怎么办?

大概有以下几种办法:

单表继承

所谓单表继承就是所有的字段都保存在一张表上,增加字段时就扩充原来的表。

这种方法优点简单粗暴,当子类型很少以及子类型的特殊属性很少的时候还是可取的。但是如果子类型达到了10几个,而且子类型的字段很多时缺点也显而易见:冗余太多,某一行记录存在许多与当前子类无关的属性,而且页面管理起来也相当繁琐,每次增加一个字段的时候,所有子类型都受到影响。

每个子类型创建一个表

添加一个子类型就增加一张表。

……

两个子类型存储完全独立,每增加一张表页面就要重新管理一张表,子类型很多的时候这种方式也不是很好。

多表继承

既有基表,又有子类型表,就像面向对象里面的继承。

多表继承的方式可以减少字段的冗余,但是同样的子类型很多时,表较多,管理起来比较麻烦。

半结构化数据模型

如果有很多子类型或者必须经常增加新的字段支持,那么可以用一个BLOB列来存储数据,用XML或者JSON格式。

Property是一个属性列:它可以用Json来存储额外增加的字段:同时包含了字段名字和值。

{
     "Field1":"Value1","Field2":"Value2"
}

这种方式实际上是在关系型数据库里运用了nosql的思想,有点实现了MongoDB的无模式文档存储的意思,但是我们都知道无模式的存储好处是扩展方便,坏处是更新修改麻烦。我们用的是sql,解析json或xml起来肯定比用C#或Java麻烦,所以使用这种方式我更倾向于将更多的业务逻辑抽离应用程序的代码中处理。

使用NoSql

这种处于关系型和非关系型之间数据存储要求,让我们第一个想到的肯定是MongoDB。而且MongoDB sql to aggregation基本实现了常用的关系型操作。但是考虑各种其他因素,这种方法成本比较高。

上面的几种方法经过反复斟酌,不用nosql那么关系型数据库还应该干关系型数据库的事情,我放弃了一开始用“半结构化数据模型”这种方式的打算,但其他两种方式我也觉得不太合适,下面说下我最后准备使用的方法。

使用行转列的方式

和多表继承类似,有一个基表用来保存各个子类型共有的字段,这张表也可以叫做索引表,故名思议索引建立在上面。

ResGenre表就是用来定义资源子类型的,ColumnMeta表用来定义新增列的元数据:

ResGenreColumnRelation表用来绑定一个子类型有哪些字段:

最后一张表来绑定一条资源记录扩展列的值:

那么如何在查询的时候获取到一个资源的扩展字段和对应的值呢?如图一个测试表有数据如下:

可以看到子类型14,15,16绑定了不同的列。

我们想要得到结果应该是这样的:

可以看到返回的结果集其实也是冗余的,对于一个ResID没绑定的列为NULL。

在sqlserver2005中实现行转列的方式不需要再用CASE WHEN了,用PIVOT方便多了:

SELECT *
FROM ColumnDataBind 
PIVOT
(
    Max(ColValue) for [ColName] in ([Age],[High],[Sex],[Weight])
)TBL

需要注意的是PIVOT中必须要用聚合函数。因为ResGenreColumnRelation表用ResID和ColName作为键,所以PIVOT聚合时ColValue只有一个,用Max就行了。

也可以跟上查询条件,减小操作数据集:

SELECT *
FROM ColumnDataBind 
PIVOT
(
    Max(ColValue) for [ColName] in ([Age],[High],[Sex],[Weight])
)TBL
where genreid =14

当然既然实现的是能随便扩展列,那么一个资源绑定了哪些列肯定不知道的,动态行转列也是必不可少的,有了PIVOT也很简单:

declare @sql varchar(8000)
select @sql = isnull(@sql + '],[' , '') + ColName from ColumnDataBind group by ColName
set @sql = '[' + @sql + ']'
print @sql

exec('SELECT * FROM ColumnDataBind PIVOT(Max(ColValue) for [ColName] in ('+@sql+'))TBL')

这是在sqlserver2005+中实现动态行转列的方式,不知道MySql有没有PIVOT。

通过这种方式当增加一个列的时候通过页面就能搞定,数据库就不需要频繁的改动了,而且更符合关系型数据库的操作。

但是写完我又在“行转列”和“半结构化数据模型”之间犹豫了?前者应该能给予更大的灵活,但总觉得哪里很别扭,后者用起来估计也比较麻烦,设计经验不足,不知道哪位大神能指点指点?

推荐阅读
  • 架构师必读:日均500万数据,如何进行数据存储选型?
    点击上方关注我,选择“置顶或者星标”作者:麦田里的老农来源:https:zhuanlan.zhihu.comp37964096小编公司有一 ... [详细]
  • 在Ubuntu中安装MongoDB
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
  • nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • 数据库基本介绍
    1、数据库基本知识概念:数据库:database(DB),是一种存储数据的仓库数据库是根据数据结构组织、存储和 ... [详细]
  • 《Python3 网络爬虫开发实战》:高效实用的 MongoDB 文档存储
    NoSQL,全称NotOnlySQL,意为不仅仅是SQL,泛指非关系型数据库。NoSQL是基于键值对的,而且不需要经过SQL ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
  • 一、前言在数据库中,慢查询日志通常是用来进行优化数据库,MySQL中存在慢查询,Mongodb中也是如此。在Mongo中的慢查询属于Mon ... [详细]
  • 1.淘宝模拟登录2.天猫商品数据爬虫3.爬取淘宝我已购买的宝贝数据4.每天不同时间段通过微信发消息提醒女友5.爬取5K分辨率超清唯美壁纸6.爬取豆瓣排行榜电影数据(含GUI界面版) ... [详细]
  • hackingTeam是如何被黑的
    hackingTeam是如何被黑的 ... [详细]
  • MySQL:互联网公司常用 分库分表
    本文目录一、数据库瓶颈IO瓶颈CPU瓶颈二、分库分表水平分库水平分表垂直分库垂直分表三、分库分表工具四、分库分表步骤五、分库分表问题非partit ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了记录一次MySQL两千万数据的大表优化解决过程,提供三种解决方案相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 目录一、MySQL数据库1.简介2.用管理员身份登录3.密码相关操作4.SQL与NoSQL5.数据库重要概念二、MySQL基本语句1.基于库的增删改查2.基于表的增删改查3.基于记 ... [详细]
author-avatar
mobiledu2502911073
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有