【问题标题】:Database structure - most common queries span 3-4 tables. Should I reduce tables?数据库结构 - 最常见的查询跨越 3-4 个表。我应该减少桌子吗?
【发布时间】:2026-02-03 20:15:02
【问题描述】:

我正在 MySQL 中为应用程序创建一个新数据库,并想知道是否有人可以就以下设置提供一些建议。我会尽量简化事情。

此数据库旨在存储与用户创建的特定项目相关的警报。反过来,需要存储与项目和/或警报相关的注释。起初我考虑了以下结构...

USERS 表 - 用于存储基本的应用用户信息(例如 user_id.name、email) - 这是我唯一确定不需要更改的部分

ITEMS 表:包含特定项目的信息(大约 4 个字段)。包含 user_id 以指示哪个用户创建/拥有此项目

ALERTS 表:包含有关警报的信息,item_id 指示警报与哪个项目相关,包含 user_id 指示哪个用户创建警报

NOTES 表:包含笔记信息、笔记所有者的 user_id、item_id(如果与项目相关联)、alert_id(如果与警报相关联)

关系:

一个项目并不总是有与之关联的警报 项目或警报并不总是有与之关联的注释

警报始终与项目相关联。同一个项目可以关联多个警报。

注释始终与项目或警报相关联。多个笔记可以与同一个项目或警报相关联。

一旦第一次创建项目信息就不太可能被用户更新。

为了论证,假设每个用户平均创建 10 个项目,每个项目平均有 2 个与之关联的警报。每个项目/警报平均有 2 个注释。

将运行的非常常见的查询:

1) 返回由特定用户创建的所有项目以及任何相关的警报和注释。给定一个 user_id,这个查询将跨越 3 个表

2) 每天检查需要发送到用户电子邮件地址的警报。 WHERE alert date==today,返回用户的电子邮件地址、项目名称和任何相关的注释。这将需要一个跨越 4 个表的查询,这就是为什么我想知道是否需要采取不同的方法...

选项 1) 一张表来涵盖项目、警报和注释。每行的 user_id 所有者。每次向项目或警报添加注释时,您都在重复警报和/或项目信息。似乎有点浪费,但项目和警报信息不会很大。

选项 2)我不认为需要查询笔记(著名的遗言?)那么如何序列化笔记数据,以便将多个笔记存储在 item 或 alert 表中的一行中(或者只是组合的 alert/项目表)

选项 3) 你还能想到什么?我问这个问题是因为我考虑过的每个选项都感觉不太对。

我很欣赏这目前是一个小项目,因此性能不应该受到太大关注,我应该只使用 4 个表。更重要的是,我的常见查询最终会变得相对复杂,这让我认为我需要重新评估结构。

【问题讨论】:

  • 过早的优化是万恶之源,在缓慢到来之前不要优化。
  • 如果您不打算查询笔记,为什么还要存储它们?
  • @johan,我不同意数据库设计,您应该始终考虑性能,这不是过早的优化(在设计中使用已知的性能杀手是糟糕的设计)。但是,我同意发帖者所做的是不正确的优化,可能还为时过早。
  • @HLGEM,我没说做坏事,等着慢吞吞和邪恶的小鬼扇你一巴掌。我的意思是,规范化你的数据库,除非缓慢需要它,否则不要去规范化。
  • @Johan,我讨厌过早的优化引用,因为太多人以此为借口,从不考虑设计中的性能。也许我见过太多那些邪恶的小精灵。当数据库没有针对性能进行设计时,它们很难修复。

标签: mysql sql database-design


【解决方案1】:

我想说,普遍的看法是只有在性能数据表明有必要时才开始规范化和去规范化。

确保您的表已正确编入索引,并具有 JOIN 的外键关系。

如果您认为最终会得到大量数据,那么这可能是考虑分区策略的好时机。按时间对快速增长的表进行分区将是很好的第一步。

【讨论】:

  • 好的,谢谢。像那时一样继续。我只是怀疑潜入并想仔细检查。
【解决方案2】:

四张表并不复杂。我通常会在具有数百个表(大多数具有数百万条记录)的数据库结构中编写访问 15 个或更多表的报告查询,我什至不会说我们的数据库只是中等大小(我们系统中的典型数据库可能有大约 200 gigs 的数据,所以不像数据库那样大)。因为它们被正确索引,它们仍然运行得很快,除非我进行非常复杂的计算。规范化,在您是一位经验丰富的数据库设计人员之前,不要考虑反规范化,并且知道不必担心表的数量。

【讨论】: