【问题标题】:How should I design the database structure for this problem?我应该如何设计这个问题的数据库结构?
【发布时间】:2011-10-07 23:25:21
【问题描述】:

我正在重建一个流量很大的网站的后台系统。

这是应用程序的核心,我构建这部分数据库的方式对于大量代码和即将开展的工作至关重要。下面描述的系统每天必须运行数百万次。我将不胜感激有关此问题的任何意见。

背景是用户可以添加他或她白天吃的东西。

简化了,流程差不多是这样的:

  1. 用户到达该站点,该站点列出了他/她当天的选择(如果之前按以下步骤所述输入)。
  2. 用户可以添加一餐(由 1 到无限种不同的食物及其数量组成)。餐点是通过搜索字段添加的,并按不同的类型进行组织(如“早餐”、“午餐”)。
  3. 在制作膳食过程中,将显示最常用的食物列表(主要由该用户提供,其次是由所有用户提供)以供快速选择。
  4. 餐点将存储在 FoodLog 表中,该表由以下内容组成:id, user_id, date, type, food_data

我目前拥有的是一个巨大的数据库,其中包含将执行搜索的食品。食品项目与通用名称(如“猪排”)和生产商(如“可口可乐”)信息以及所需的其他详细信息一起存储。

问题总结:

我的问题是我不知道存储数据的最佳方式,以便以我需要的方式轻松访问它,并且数据库不会失控。

假设有 100 万用户每天添加 1 到 7 顿饭。为了存储每餐的每种食物,每天,每个用户每天可能会创建 (1*avg_num_meals*avg_num_food_items) 百万行。

以某种压缩方式存储数据(比如 food_data 是一个 json_encoded 字符串),会显着减少行数,但同时也难以创建“最常用的食品”列表和其他统计信息在飞行中。

应该把表拆分成几张表吗?如果是这样,他们将如何互动?

该网站目前托管在中档 CDN 上,并使用 LAMP(Linux、Apache、MySQL、PHP)主干。

【问题讨论】:

  • 您遇到了经典数据库设计者的困境:规范化还是不规范化。
  • 你不是说VPS而不是CDN。可以安装软件吗?如果可以的话,我建议您使用 Redis 或 memcached 研究缓存(使读取速度极快)。另外,我建议您查看 APC 以获取 PHP 脚本的编译字节码。

标签: php mysql database performance database-design


【解决方案1】:

粗略地说,您需要一个完全规范化的数据结构。您想为用户提供一张桌子,为膳食提供一张桌子(每餐一个条目,引用用户;您可能还希望在此表中包含用餐的时间/日期),以及用于 MealItems 的表,其中只是 Meal 和 Food Items 表之间的关联表。

因此,当用户进入并创建帐户时,您会在用户表中创建一个条目。当用户报告他们吃过的餐点时,您会在 Meals 表中创建一条记录,并在 MealItems 表中为他们报告的每个项目创建一条记录。

这种结构使得每顿饭都可以简单地拥有可变数量的物品,而不会浪费很多空间。您可以通过一个相对简单的查询来确定膳食中项目的表示,以及确定任何一个用户在任何给定时间跨度内消费的总项目集。

这种规范化的表结构将支持非常大量的记录,并支持对数据库的大量查询。

【讨论】:

  • 阅读规范化并了解 1NF 到 4NF 我意识到我可能反对在多个表上使用 JOIN。我试图在最长的时间内避免它,但对我来说越来越明显的是它是必要的和良好的做法。很好的答案!
  • @Mattis:很高兴为您提供帮助。是的,JOIN 绝对是你的朋友。一旦您对它们感到满意,您就会惊讶于它们的实用性以及它们的表现。
【解决方案2】:

首先,

以某种压缩方式存储数据(例如 food_data 是 json_encoded 字符串)

不推荐。随着新需求的增加,这将在未来给您带来无数麻烦。

这里绝对应该有几张桌子。

Users
id, etc

Food Items
id, name, description, etc

Meals
id, user_id, category, etc

Meal Items
id, food_item_id, meal_id

Meal Items 会使用 id 将 Meals 与 Food Items 联系起来。餐食将使用 id 与用户绑定。这使得使用连接来获取数据总计、平均值等的详细列表变得很简单。如果字段被正确索引,这应该是支持大量记录的一个很好的模型。

【讨论】:

  • 哈哈“可怕”很好,当重要的点被提出时,我不会吝啬苛刻的词。谢谢你的帖子,我意识到我需要对我的数据库设计进行相当多的改造。
【解决方案3】:

除了been said

  • 谨慎使用索引。将这些正确应用到您的数据库可以显着加快对表的读取访问速度。
  • 考虑使用特定于语言的功能来最小化空间。你提到你正在使用mysql;考虑在适当的时候(食物类型、膳食类型)使用ENUM,以最小化数据库大小并简化管理。

【讨论】:

    【解决方案4】:

    我会把你的饭桌分成两张表,一张表为每顿饭存储一行,第二张表为一顿饭中使用的每种食物项目存储一行,外键引用它所用的饭菜在。

    之后,只需确保在连接或 WHERE 子句中使用的任何表列都有索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-11
      • 2017-10-04
      • 1970-01-01
      • 1970-01-01
      • 2016-06-24
      • 2011-10-13
      • 2020-12-07
      相关资源
      最近更新 更多