我正在解决课堂上的一个问题,以设计一个存储与一个人相关联的事件列表的 web 的 mySQL 表示。因此,对于这个表/表,它将有 2 列,其中一列是人名,另一列是事件。但是,一个人通常会有 30 到 1000 个事件,因此我们计划为整个 6000 名学生的本科班使用的这张表将有数百万个条目。有没有更好的方法将它存储在 mySQL 中,占用更少的空间,但仍然能够检索单个事件和参加它的人员列表,就像它是一个两列的表一样容易?
3 回答
是的,有一种称为many-to-many的技术,基本上将您的一个表分成三个,当您考虑到确实有三个实体正在建模时(作为一个良好的完整性检查),这一点至关重要
- 人
- 事件
- 一个人与一个事件的关联
您将其建模为三个表,前两个表基本上各有两列:一个具有唯一索引(称为“主键”),第二个是语义名称(人名、事件名称)。请注意,您也可以在其中添加任意数量的列,而只需增加一个存储空间(您的第一步很可能是在事件表中添加一个日期列)。
第三个表很有趣,它只包含 2 列,每列都是数字,这两个列都是对其他表的引用(每一行很简单:(person_id, event_id))。我们称这些“外键”。
这种结构意味着几件事:
- 无论某人参加了多少活动,该人只代表一次。
- 与活动相同,无论有多少参加者
- 出席是一个“一流”的实体,并且可以增长到包括它自己的属性(即“角色”)
这种结构之所以称为多对多,是因为每个人可能参加许多活动,而每个活动可能有许多参加者。
该设计的典型特征是没有重复单个领域知识,只有必要时重复“键”以模拟真实世界的领域。(即在您的第一个示例中,考虑名称更改将需要未知数量的更新,并可能导致数据异常,避免这种情况是数据库规范化的主要关注点。
不要担心“空间”。这不是 1970 年代,我们不会用完穿孔卡片上的列来存储数据。您应该关心用正确的、最规范的数据结构表达您的需求。使用适当的索引应该没有问题,而不是这样的数据量。
请记住,索引需要在您将包含在子句中的任何内容上定义,有时您可能需要为使用和WHERE
获取的大型列表添加额外的索引。ORDER BY
LIMIT
尽可能或实际使用整数标识符而不是字符串。这些存储为少量字节,通常为 4,而可变长度字符串通常至少是字符串的长度(以字节为单位加 1)。
一个适当规范化的数据库无论如何都会使用数字标识符,所以如果事情不是一个大问题,这种情况。只有当您遇到无法使用其他方法轻松解决的合法性能问题时,您才会反对这一点,或者故意对数据进行非规范化。
与往常一样,通过生成大量虚拟数据来测试您的架构并查看其执行情况。由于您事先对需求有一个很好的了解,请在这些级别上进行一些测试,然后,为了安全起见,尝试 2 倍、5 倍和 10 倍的数据,看看您的设计有多大的灵活性。只要您知道您将体验到什么样的规模,就有性能限制是可以的。
mySQL 关系数据库是专门为处理此类问题而设计的。处理数百万个条目不是问题。复杂的查询可能需要几秒钟,但会执行得非常好。
最好的设计是每行存储 1 个事件。你的方式听起来是最好的方式。祝你好运。