MySQL:将一张表拆分为多张表(相同的列)以提高性能?

Posted

技术标签:

【中文标题】MySQL:将一张表拆分为多张表(相同的列)以提高性能?【英文标题】:MySQL: splitting one table to multiple tables (same columns) for performace increase? 【发布时间】:2009-12-04 22:43:33 【问题描述】:

这个问题是关于性能,而不是可能的解决方案。

我的系统包含许多不同类别的项目。每个类别都有自己的表格,因为每个表格都有很多行并且字段不同。

ItemA - id, fld1, fld2
ItemB - id, fld1, fld3, fld4
ItemC - id, fld1, fld3, fld5
....

现在需要管理用户库存,这意味着用户是否有物品。一种选择是使用单个表:

Inventory - category_id, item_id, user_id

对于 ItemA、ItemB、...行,category_id 是不同的,这就是我们区分的方式。

第二个选项是:

InventoryA - item_id, user_id
InventoryB - item_id, user_id
...

第一个选项可能是最容易管理的,但是库存表很大(数量级:所有类别的项目数乘以用户数)并且经常更新和经常查询。

第二个选项会有点难以管理(因为我们为每个类别创建了一个新的库存表),但可能会带来性能提升,因为它可能会阻止竞争条件。由于类别是完全隔离的,因此单个查询可能需要涉及多个库存表。

目前系统使用 mysql 和 InnoDB 引擎。 大约有 10 个类别,但预计在不久的将来会增长到几十个。最大的类别有 > 200k 个项目,大多数有 > 10k 个项目。 单个库存表有超过 1000 万行,预计会随着更多用户的加入而变得更大。

我知道最好的办法是测试这两种方法的性能并做出决定,但事实是,转向多表设计并不是那么快速和轻松。

如果您有类似问题的个人经历,请分享。

谢谢

【问题讨论】:

一个项目可以被多个用户拥有(使用)吗? 是的,达米尔,这是一个多对多的关系。 【参考方案1】:

规范化数据库通常会更好地提高性能和可维护性。

此方法将创建一个与 ItemA、ItemB 等具有 1:1 关系的表 Items。然后您可以创建一个与基本 Items 表具有关系的 Inventory 表。

根据documentation,InnoDB 支持行级锁,因此无需使用多表来防止死锁。

【讨论】:

感谢 Andomar 的回答。但是,恕我直言,您的建议实际上是一个非常糟糕的主意,会进一步降低性能。目前,我提出的第一个解决方案已经实现。数据库上的每个查询仅与其中一个类别相关,我真的无法理解添加额外的 Items 表将如何提高性能。标准化是一个很好的概念,但这里的问题是关于实际性能的影响。是的,InnoDB 支持行级锁,但我害怕的不是死锁,而是性能下降。 @Colnector:添加基表可以让inventoryitem之间有外键关系 是的@Andomar,我明白这一点,但我真的不明白这对我所问的问题有何帮助。目前我有inventory(category_id, item_id, user_id) 并且根据你的建议我会有inventory(item_id, user_id) 但是我必须在新的Item 表上加入每个查询。这会降低性能。 @Colnector。当您要求答案时会变得很愚蠢,这意味着您不知道,然后与知道该主题的人的答案争论。您是否有任何证据(不是想法)表明非规范化的执行速度比规范化的更快。【参考方案2】:

这是我对这个故事的看法,希望能有所帮助。

项目表具有所有项目共有的字段。 类别(A、B、C)表具有特定于每个表的字段。 一个用户有很多项目,一个项目可以被多个用户使用。

【讨论】:

感谢 Damir,这类似于 Andomar 上面的建议。请在那里查看我的评论。漂亮的草图:)

以上是关于MySQL:将一张表拆分为多张表(相同的列)以提高性能?的主要内容,如果未能解决你的问题,请参考以下文章

SQL多张表如何合并成一张报表?

百万级数据mysql分区

SQL问题,怎么将一张表的某个字段更新为另一张表的字段

关于数据库表的水平拆分和垂直拆分

MySQL 分区表原理及使用详解

MySQL如何实现分库分表,如何提高查询效率