数据库设计---关于建表的时候选择横标和竖表(纵表)的一点思考

本文出处:http://www.cnblogs.com/wy123/p/6677073.html

在做数据统计类数据库设计的时候,在考虑数据存储的时候,经常会遇到逻辑上同一个BusinessID对应多个数据点的情况,
比如工资表中的员工ID以及各项工资信息,财务表中的各个报表Id和多个数据点之间的信息
面对这种情况,如何来设计表结构,是横表,还是竖表,各有那些优缺点,本文将做一个粗浅的分析。

横标和竖表的表现形式

日常生活中也有很多类似的例子,先用一个Excel画一个例子,比如工资表
这么做就是“横表”,特点是,一个ID对应所有的值信息,以行Key-Value1-Value2-Value3的方式存储

如下是竖表(纵表),特点是每行仅存储该ID的某一个类别字段的值,以行的方式存储Key-Value的方式存储

横标和竖表的设计示例

  下面通过一个具体的例子来说明横标和竖表的一些特点

--横标
CREATE TABLE HorizontalTable
(
    Id                int identity(1,1),
    BusinessId        varchar(50)         ,
    CategoryVal1    varchar(20)         ,
    CategoryVal2    decimal(20,5)     ,
    CategoryVal3    datetime         ,
    CategoryVal4    varchar(20)         ,
    CategoryVal5    varchar(20)         ,
    CategoryVal6    varchar(20)
)
insert into HorizontalTable  values (‘BH000001‘,‘value1‘,89.12,‘20170406‘,‘abc4‘,‘abc5‘,‘abc6‘)
insert into HorizontalTable  values (‘BH000002‘,‘value2‘,99.11,‘20170407‘,‘abc4‘,‘abc5‘,‘abc6‘)

--竖表
CREATE TABLE VerticalTable
(
    Id                int identity(1,1),
    BusinessId        varchar(50),
    CategoryKey        varchar(20),
    Val                varchar(20)
)
insert into VerticalTable values (‘BH000001‘,‘CategoryKey1‘,‘values1‘)
insert into VerticalTable values (‘BH000001‘,‘CategoryKey2‘,89.12)
insert into VerticalTable values (‘BH000001‘,‘CategoryKey3‘,‘20170406‘)
insert into VerticalTable values (‘BH000001‘,‘CategoryKey4‘,‘abc4‘)
insert into VerticalTable values (‘BH000001‘,‘CategoryKey5‘,‘ab5‘)
insert into VerticalTable values (‘BH000001‘,‘CategoryKey6‘,‘ab6‘)
insert into VerticalTable values (‘BH000002‘,‘CategoryKey1‘,‘values2‘)
insert into VerticalTable values (‘BH000002‘,‘CategoryKey2‘,99.12)
insert into VerticalTable values (‘BH000002‘,‘CategoryKey3‘,‘20170407‘)
insert into VerticalTable values (‘BH000002‘,‘CategoryKey4‘,‘abc4‘)
insert into VerticalTable values (‘BH000002‘,‘CategoryKey5‘,‘abc5‘)
insert into VerticalTable values (‘BH000002‘,‘CategoryKey6‘,‘abc6‘)

横表中的数据:

竖表中的数据

  

可能实际应用中,要比这个示例中的情况更加复杂,那么在设计表结构的时候,如何选择横标或者竖表?
首先来看横标的特点

对于横表
  1,同一个Key值对应的列是固定的,比如,比如HorizontalTable中有6个字段
  2,各个字段的值是自由的,比如HorizontalTable中的CategoryVal1是varchar类型的,CategoryVal2是decimal的
  3,表中并不存储描述性字段本身(相比纵表)
  4,相比竖表,存储同样多的数据,行数要少
对于竖表
  1,同一个Key值对应的列是动态的,因为是按照行存储的,可以存储成Key1—Value1,Key1—Value2,Key1—Value3的方式存储
  2,字段的类型是固定的,但是类似是要兼容的,不能有个性化的字段,比如VerticalTable中的CategoryKey+Val,因为固定了这么一个字段
  3,表中需要存储描述字段本身(相比横标),要根据BusinessKey值的不同,重复存储CategoryKey
  4,相比横表,存储同样多的数据,行数要多

综上可以看出,
  横标的优点:横标的有点事显示的较为清晰直观,同时在字段的选择上更为科学合理,具体的字段可以根据具体情况划分字段类型,
  横标的缺点:不方便扩展和公用,也就是说设计了一张横标,只能在固定的某一种特定的相对不变的场景下使用,
        比如加字段,或者类似的业务想公用一张横表,都有局限

  竖表的优点:最大的特点是可以灵活扩展存储的内容,同时具有一定的公用性
        因为竖表的存储结构不受字段个数的限制,可以存储具有一定共性的业务数据。
  竖表的缺点:竖表的字段类型要兼容,比如横标可以根据具体的值设计成varchar,decimal,datetime等,
        横标为了兼容以上字段类型,只能设计成varchar的,可能会浪费一定的空间

  横标和竖表主要考虑的是扩展性和共同性,对于显示方式问题,个人认为倒是问题不大,无非是行转列和列转行的问题
  如下是一个将上述设计的横表转竖表和竖表转横标的示例,也不复杂,因此说,显示的问题不是大问题

select * from HorizontalTable
--列转行
;WITH HorizontalCET
AS
(
    SELECT Id,BusinessId,CategoryVal1,
            cast(CategoryVal2 as varchar(20)) as CategoryVal2,
            cast(CategoryVal3 as varchar(20)) as CategoryVal3,
            CategoryVal4,
            CategoryVal5
    FROM HorizontalTable
)
SELECT Id,BusinessId,ColumnName,ColumnVal
FROM HorizontalCET
UNPIVOT (ColumnVal FOR ColumnName IN
            (CategoryVal1,
            CategoryVal2,
            CategoryVal3,
            CategoryVal4,
            CategoryVal5)
        ) tmp

--列转行
select * from VerticalTable
SELECT * FROM
(
    select BusinessId ,
           CategoryKey,
           Val
    from VerticalTable
)t
 PIVOT( MIN(Val) FOR CategoryKey IN (CategoryKey1,
                                    CategoryKey2,
                                    CategoryKey3,
                                    CategoryKey4,
                                    CategoryKey5,
                                    CategoryKey6)
)a

  

关于横表和竖表的性能问题

  关于性能问题,很难一概而论,还要结合具体的情况作分析,比如查询方式,查询数据了,索引结构等等都有一定的关系。
  表面上看,竖表存储了大量冗余的数据,浪费了一定量的磁盘空间是事实,但是极端情况下横表也有可能造成极大的空间浪费
  了解SQL Server的同学肯定知道,
  SQL Server中正常来来说是行存储,一行数据不能跨页存储(当然forwarded存储方式的数据除外,有机会说这个),
  SQL Server的最小存储单位是页(Page),一个页的大小是8kb,除去page信息固定占用的空间之外是8060个字节,
  每一行固定的一行数据除了数据自身占用的空间外,至少(不是一定,表结构越复杂占用的额外空间越大)还要占用1+1+2+2+1=7个字节

  对于宽表,一旦字段长度达到一定的程度,
  比如每行长度为800个字节,理论上将,在一个page上,存储9行记录之后,还剩余800字节的空间(具体剩余多少跟表结构有关,这里只是举例说明),
  对不起,第十行数据来了已经存不进去了,只能新开页面分配存储空间,这样,当前这个页面就浪费了800字节的存储空间
  反观竖表,因为存储的数据行都非常短,即便发生上述情况,也只会浪费很少的一点数据空间(小于一行数据的空间)
  极端情况下会更加有意思,参考这个http://www.cnblogs.com/studyzy/archive/2008/11/27/1342003.html

  

  有上述可见,对于横表和竖表,不管是设计上还是存储上,优点和缺点都是看站在哪个角度来看的,
  从一个角度来看是有点,从另外一个角度看就可能会变成缺点,只有舍弃一部分,根据实际情况权衡之后做出取舍。
  凡事无绝对,适合即可。

总结:

  本文从适应场景、存储、性能等方面粗浅第分析了表设计时候横标和竖表的特点和优缺点,
  具体设计的时候可综合考虑,做出合理的选择。
  另外,本文肯定还有没有预计或者说想到的情况以及评估方向,也希望有想法的同学补充,谢谢。

    

时间: 2024-10-26 01:33:22

数据库设计---关于建表的时候选择横标和竖表(纵表)的一点思考的相关文章

大数据量查询优化——数据库设计、SQL语句、JAVA编码

数据库设计方面: 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描.             如: select id from t where num is null              可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0 3

优化MySchool数据库设计总结

数据库的设计 一:什么是数据库设计? 数据库设计就是将数据库中的数据实体以及这些数据实体之间的关系,进行规范和结构化的过程. 二:为什么要实施数据库设计? 1:良好的数据库设计可以有效的解决数据冗余的问题 2:效率高 3:便于进一步扩展 4:使得应用程序开发变得容易 三:设计数据库的步骤 第一步    需求分析:  分析客户的业务和数据处理需求(收集信息,标识实体,标识每个实体需要存储的详细信息,标识实体间的关系) 第二步    概要设计:  绘制E-R图,用于与客户或团队成员的交流 第三步  

数据库设计笔记

数据库设计学习笔记! 先谢慕课网. 什么是数据库设计? 数据库设计就是根据业务系统的具体需要,结合我们所选用的DBMS(数据库管理系统),为这个业务系统构造出最优的数据存储模型.并建好数据库中的表结构及表与表之间的关联关系的过程.使之能有效地对应系统中的数据进行存储,并可以高效的对已经存储的数据进行访问. NoSQL系统:Mongo/ Memcache/ Redis 为什么要进行数据库设计? 优良的设计:     减少数据冗余     避免数据维护异常     结构存储空间     高效的访问糟

数据库设计之冗余字段设计

在设计数据库时,某一字段属于一个表,但它又同时出现在另一个或多个表,且完全等同于它在其本来所属表的意义表示,那么这个字段就是一个冗余字段. --以上是我自己给出的定义 冗余字段的存在到底是好还是坏呢( 冗余是为了效率,减少join.单表查询比关联查询速度要快.某个访问频繁的字段可以冗余存放在两张表里,不用关联了. )?这是一个不好说的问题.可能在有人看来,这是一个很蹩脚的数据库设计.因为在数据库设计领域,有一个被大家奉为圭臬的数据库设计范式,这个范式理论上要求数据库设计逻辑清晰.关系明确,比如,

数据库设计---入门

1.     数据库设计的概述 1.1.   数据库设计是什么 所谓的数据库设计就是根据需求文档的描述将需求转成数据库的存储结构的过程. 在数据库设计的流程上,我们通常根据需求,画出数据的ER图.然后在通过ER图生成数据库的建库脚本.(Entity Relational) ER图,所谓的ER图就是数据库关系图 为什么我们使用ER图来实现数据库设计的设计呢? 1.可见即可得.使用ER图可以通过图形的方式展示表与表直接的关系 2.可以根据设置的数据库,方便生成不同的数据库的SQL建库脚本 3.可以快

规范化-数据库设计原则

关系数据库设计的核心问题是关系模型的设计.本文将结合具体的实例,介绍数据库设计规范化的流程. 摘要 关系型数据库是当前广泛应用的数据库类型,关系数据库设计是对数据进行组织化和结构化的过程,核心问题是关系模型的设计.对于数据库规模较小的情况,我们可以比较轻松的处理数据库中的表结构.然而,随着项目规模的不断增长,相应的数据库也变得更加复杂,关系模型表结构更为庞杂,这时我们往往会发现我们写出来的SQL语句的是很笨拙并且效率低下的.更糟糕的是,由于表结构定义的不合理,会导致在更新数据时造成数据的不完整.

数据库设计的3大范式

数据库设计范式 什么是范式:简言之就是,数据库设计对数据的存储性能,还有开发人员对数据的操作都有莫大的关系.所以建立科学的,规范的的数据库是需要满足一些 规范的来优化数据数据存储方式.在关系型数据库中这些规范就可以称为范式. 什么是三大范式: 第一范式:当关系模式R的所有属性都不能在分解为更基本的数据单位时,称R是满足第一范式的,简记为1NF.满足第一范式是关系模式规范化的最低要 求,否则,将有很多基本操作在这样的关系模式中实现不了. 第二范式:如果关系模式R满足第一范式,并且R得所有非主属性都

夺命雷公狗ThinkPHP项目之----商城2数据库设计

重要难度:五星 难度:无形 数据库的设计,就是体现了你对业务逻辑的了解 数据库设计的好坏,有时候决定了项目的成败 要点: 表与表之间的关系(一对一,一对多,多对多) 每一个字段的数据类型(数值,字符串,日期时间)没有布尔类型,使用tinyint来代替,1是真,0是假 设计数据库,以商品为例 找到核心(中心),然后一步步的展开 核心->商品 先来初步设计一下商品表的字段: 名称.价格.图片.颜色.上架时间.各种规格参数.详细描述,库存,品牌.分类. 品牌和商品是两个不同的东西,设计表的一个理念:一

MySql三大范式与数据库设计和表创建常用语句

[数据库设计的三大范式] 1.第一范式(1NF First Normal Fromate):数据表中的每一列(字段),必须是不可拆分的最小单元.也就是确保每一列的原子性. 例如: userInfo: '山东省烟台市 13181621008' => userAds:'山东省烟台市' tel:'13181621008' 2.第二范式(2NF):满足1NF后,要求:表中所有的列,都必须功能依赖于主键,而不能有任何一列与主键没有关系.(一张表值描述一件事情) 3.第三范式(3NF):满足2NF后,要求: