请教表结构设计问题:一对多。

本帖最后由 misscai 于 2011-01-07 09:25 编辑

最近做一个项目,设计一个表结构,用于记录个人的兴趣爱好,目前的表结构设计如下。
create table Person  --人员表
(ID    int,    --唯一索引
Name   varchar(20),  --姓名
Hobby_ID      varchar(50))  --兴趣爱好ID

create table Hobby   --爱好
(ID   int,   --唯一索引
Hobby_Name varchar(10))  --兴趣爱好表述

表的数据如下:
ID      Name                   Hobby_ID
----   --------------------   -----------------
1       张三                         1,2,3
2       李四                         1,3
3       王五                         2

ID                 Hobby_Name
---------------  -----------
1                   游泳
2                   健身
3                   旅游

我遇到的问题是erson.Hobby_ID用字符串记录兴趣爱好的枚举ID,在程序中处理时每次都要对字符串进行拆分后,再与Hobby表进行关联,十分影响性能。
我试想过用中间表记录兴趣爱好,后来察觉中间表可能会非常大。
我的中间表设计如下:
Person_ID         Hobby_ID
--------------    ------------
1                      1
1                      2
1                      3
2                      1
2                      3
3                      2
因为在业务环境中,Person表数据集是千万级的,Hobby表数据集也是不确定的。
所以,各位大虾在设计这种表结构时是如何做的?

作者: misscai   发布时间: 2011-01-07

建议:爱好不要用like , like是个关键字。 看着不爽。  用hobby也行啊。


人员表的兴趣爱好ID建议改成integer类型,爱好表需要3列(或以上)
create table hobby (
   hobby_id int not null,                          ---爱好ID
   seq        int not null,                          ---爱好的序号
   hobbies   varchar(255) null                  ---爱好内容
)

楼主需要看看关系型数据库的理论。

作者: andkylee   发布时间: 2011-01-07

你的人员表中爱好列存储1,2,3这样的数据。 甚至可以说都不满足关系型数据库的第一范式的要求了。

作者: andkylee   发布时间: 2011-01-07



QUOTE:
建议:爱好不要用like , like是个关键字。 看着不爽。  用hobby也行啊。


人员表的兴趣爱好ID建议改成 ...
andkylee 发表于 2011-01-07 09:21




    谢谢你的建议,已改。
若按照你的方案,Person.Hobby_ID改为Integer字段,那多个兴趣如何记录?
请赐教!

作者: misscai   发布时间: 2011-01-07

seq        int not null,                          ---每个人的爱好的序号

作者: andkylee   发布时间: 2011-01-07

其实ankylee就是直接用你的那个联立表来做数据表就最合适了。上面建上合理的索引和分区应该就不错了。
换言之——以空间换效率。

作者: Eisen   发布时间: 2011-01-07

你的这个例子和数据库管理系统中的一个表有多列相似嘛。

兴趣爱好中存储,1,2,3这样的数据, 感觉你像是在开发程序, 而不是在设计表结构。


create table persion   --爱好
(ID   int,   --唯一索引
name varchar(20),
hobby_id  int  --兴趣爱好表述

create table hobby (
   hobby_id int not null,                          ---爱好ID
   seq        int not null,                          ---爱好的序号
   hobbies   varchar(255) null                  ---爱好内容
)

查询某人的所有兴趣爱好,用如下的SQL:
select p.name,h.seq,h.hobbies from person p,hobby h
where p.hobby_id  = h.hobby_id
         and p.name='张三'


这样的设计难道不是很简单吗?

作者: andkylee   发布时间: 2011-01-07

回复 Eisen


    像这种场景,我觉得不能用数据分析的那套理论来用空间换时间。原因:如果人员表还有其他的如性别、年龄、籍贯、电话等信息的话,数据冗余度很高;数据可能需要经常更新(人的兴趣在变嘛,呵呵~);查询的话可能会查询某人的所有兴趣,或者有某个特定兴趣的人员信息。

建索引、表分区都是提高性能的方法。

作者: andkylee   发布时间: 2011-01-07