欢迎投稿

今日深度:

数据库设计之存储多值的问题,数据库存储

数据库设计之存储多值的问题,数据库存储


     存储多值的问题在设计数据库时是很普遍的问题,看到很多开发人员在上面吃了亏,我觉得有必要拿出来说。

     业务场景:一个业务单据,有多个联系人。一个设备维护工作,有多个维护班组。下面来举个例子

    createtable BILL

    (

     bill_id numberprimarykey,

     bill_name varchar2(20),

     bill_contentvarchar2(200),

     contact_idnumber--来至于user表的user_id

    );

1. 在起初的设计中,联系人只有一个,后来需求有变化了,联系人又多个。有几种方案:

方案一:在加几个字段,contact_id1,contact_id2,contact_id3...。

方案二:把contact_id的number类型改为varchar2,多值一起存储,值与值之间用分割符隔开(如逗号)。

方案三:再加一张表bill_contact

createtable bill_contact

(

  bill_id number,

  contact_idnumber

);

altertable BILL_CONTACT

  addconstraint pk_bill_contactprimarykey (BILL_ID,CONTACT_ID);

2. 对比几个方案

方案一显然不合适,不知道建几个字段合适,就算知道最多有几个联系人,查询起来也很麻烦。查询单中包含联系人100和101的记录,

select *from bill_contact

 where (contact_id =100and contact_id1 =101)

    or (contact_id =101and contact_id1 =100);

     查询单中包含联系人100的记录,

select *from bill_contact

 where (contact_id =100or contact_id1 =101 or.);

 

     方案二的优点在于方便,开发人员只需要改动少量的代码,普遍被开发人员采纳。a. 但好景不长,分析、统计功能非常难做,如需要列出在某一段时间内某一位联系人的所有单据;统计出每张单据联系人的数目等。

b. 查询也会变得不高效,类型不一致导致隐式转换,索引失效。

c. 修改起来复杂,需要额外在代码中写一段逻辑处理。

d. 有的系统主键用的是32位UUID,如果联系人又10位,那这个字段长度得是500,有点恐怖。

select *from bill_contact

 where contact_idlike'100,%'

    or contact_id like'%,100'

    or contact_id like'%,100,%';

     早前针对这种问题我专门写过优化的方案,数据库设计中单个字段多值的处理

    

      方案三恰好是弥补了方案二的众多确定,开发人员总是担心表关联的性能太差,其实是多余的,因为此时能走到索引。还有一个好处就是可以对联系人的信息进行扩展,如是第一联系人,还是第二联系人,这是方案二无法实现的。改造对于开发人员来说工作量比方案二要大。

    select *from bill_contact a, bill_contact b

    where a.bill_id = b.bill_id

and b.contact_idin (100,101);

3. 多值的问题如何抉择呢?

  方案一肯定是不要选的。

  方案二适合于对多值列没有分析统计,没有查询。

  方案三是我心中理想的方案,虽然它可能会造成一些工作量。


数据库设计含有多值属性的表

这样设计不行啊,主要是在一个表里的ID是唯一的,后面没有办法跟多纪录。
需要拆开成两个表,用一个列关连起来。
1: nametb: id int(10),name varchar2(20),serialno int(10)
2: teltb: name varchar2(20),tel number(11)
1表是唯一的,2表是多行的。
可以实现你的目标。
 

数据库存储问题

对于固定表,每个字段占用的空间是固定的,对于整数类型的字段,无论数值是多大、多小占用字节数都相同,对于字符串字段,无论长度多长、多短占用的字节数都相同,长度超过字段定义宽度的部分无法存储,长度低于字段定义宽度的部分浪费。

对于动态表,里面字符串类型字段的长度会影响占用物理空间的大小,超过定义长度的仍然无法存储,但是存储内容低于定义最大长度的能节省空间。

一般情况下,只要表有一个字段是变成字符串类型(VARCHAR),那么这个表就是动态表,所有的字符串类型(CHAR)字段实际上都是变长的。相反,如果没有任何一个VARCHAR字段,那么这个表就是固定的。

对于动态表,可以节省存储空间,但是速度会变慢,道理很简单,特别是修改一个记录长度发生变化的时候,系统要做许多事情。

以上的动态和固定,都只针对字符串类型,如果你的表都是存储整数,那么肯定是固定的。无论存储的整数多大、多小,占用的空间都是一样的。

另外,对于允许为空的字段,该字段占用的空间要多一点,该类字段的物理存储中要多一个记录内容是否为空的地方。但是,对于允许为空的字段,如果是固定表、或者动态表的非字符串类型字段,其占用的空间是固定的,只有在动态表的字符串类型字段里面,为空的字符串要比有内容的字符串少占用空间。
 

www.htsjk.Com true http://www.htsjk.com/shujukunews/3378.html NewsArticle 数据库设计之存储多值的问题,数据库存储 存储多的问题在设计数据库时是很普遍的问题,看到很多开发人员在上面吃了亏,我觉得有必要拿出来说。 业务场景:一个业务单据,有多...
评论暂时关闭