Mysql:多个表还是一个大表?

Mysql:多个表还是一个大表?,mysql,performance,optimization,innodb,Mysql,Performance,Optimization,Innodb,这个问题已经被问过了,但我还没有找到“1个声音的答案” 这样做是否更好: 1张大桌子,带: 用户id |属性|属性| 2 |属性| 3 |属性| 4 或4个smal表格,带有: 用户id属性1 用户id属性2 用户id属性3 用户id属性4 一张大桌子还是许多小桌子?每个用户只能有一个属性X的值。我们有很多数据要保存(1亿用户)。我们正在使用innoDB。性能对我们来说非常重要(10000次查询/秒) 谢谢 François如果您坚持零、一或多原则,即不存在这样的东西,其中一个,或者数量

这个问题已经被问过了,但我还没有找到“1个声音的答案”

这样做是否更好:

  • 1张大桌子,带:
用户id |属性|属性| 2 |属性| 3 |属性| 4

  • 或4个smal表格,带有: 用户id属性1
用户id属性2

用户id属性3

用户id属性4

一张大桌子还是许多小桌子?每个用户只能有一个属性X的值。我们有很多数据要保存(1亿用户)。我们正在使用innoDB。性能对我们来说非常重要(10000次查询/秒)

谢谢


François

如果您坚持零、一或多原则,即不存在这样的东西,其中一个,或者数量不限,那么您将始终构建适当的规范化表来跟踪这样的事情

例如,一个可能的模式:

CREATE TABLE user_attributes (
  id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
  user_id INT NOT NULL,
  attribute_name VARCHAR(255) NOT NULL,
  attribute_value VARCHAR(255),
  UNIQUE INDEX index_user_attributes_name(user_id, attribute_name)
);
这是基本的键值存储模式,每个用户可以有许多属性

虽然这方面的存储要求比固定列的存储要求更高,但像
attribute1
这样的名称总是令人沮丧,在TB大小的硬盘时代,成本很低,几乎不成问题

通常,在插入时间出现问题之前,您会为此数据创建一个表。只要你的插入速度快,我就不担心了。在这一点上,您需要考虑一种区分策略,将该数据划分为具有相同模式的多个表,但仅当需要时才使用。 我可以想象这将处于~1000-5000万行的阶段,但如果此表中的插入活动量相对较低,则可能会更高

不要忘记,优化读取活动的最佳方法是使用缓存:最快的数据库查询是您不进行的查询。对于这类事情,您通常使用类似于存储以前获取的结果的东西,并且您会在写入时使其无效

一如既往,在生产规模上对任何提议的方案进行基准测试。

1大表,包括: 用户id |属性|属性| 2 |属性| 3 |属性| 4


这将使你的管理更容易。否则,过多的单独查找也会使针对DB的编程复杂化,并有可能增加应用程序错误。

这取决于您想对数据做什么,但从您的描述来看,两者都不是最理想的。相反,您可以有一个具有以下内容的表:user_id、attribute_num、attribute——因此,由于每个用户只有一个attribute_X的值,因此它只包含3个可以索引的字段中的所有内容。对于某些特定任务,这可能不是最好的选择,但这取决于您想要什么。您需要问自己的问题是,您通常需要在同一查询中为同一用户获取多个属性吗?如果您得到多个,并且它们位于不同的表中,那么由于需要表联接,性能会变慢。@sn00k4h我们通常只进行原子选择/更新(出于缓存原因,一次只有一个属性)。因此,对于请求10个属性,我们进行了10次调用(但可能只有1或0个请求,取决于缓存状态)。@Ynhockey我们不能使用“user\u id,attribute\u num,attribute”,因为属性字段可以是int,bigint,date,float,等等…尝试以您提到的方式优化缓存命中可能会或可能不会实际提高性能,这取决于各种因素。如果我是你,我会尝试不同的可能设计,并比较性能,因为这是你知道的唯一(更)确定的方法。对于不同的数据集,相同的设计可以执行非常不同的操作。另外,您可以尝试的另一种可能的设计是两种方法的混合-将“属性”与相对较小的数据类型(例如:int、date)放在同一个表中,并将较大的数据类型分开。您好,谢谢您的回答。问题是我们对属性值(排序、筛选等)提出了请求,每个属性可以不同(日期、int、bigint、float)。所以我们不能使用Varchar来存储属性数据。如果您有一个固定的模式,那么创建具有适当类型的列,每个用户一条记录。您使用的
attribute1
等示例是一些应用程序的典型示例,在这些应用程序中,该列就是这样称呼的。你所做的听起来像是它会融化,除非你在上面加上某种搜索引擎,以减轻服务器的压力。MySQL需要性能良好的索引,但大型、复杂的索引会降低插入时间。这种键值方法的一种变体是有多个值表,每种类型一个,您需要从所有值表中进行选择并将它们组合在一起。将为特定的
属性名称
属性名称
用户id
组合设置索引。但是,如果您真的想扩展这一点,可能需要某种map reduce层将查询分散到N个数据库实例。如果您这样做,您希望您的表尽可能简单和通用。请记住,从大型表中删除列非常困难,但删除表示列的表更容易。我不确定你会如何处理你的特殊情况,因为不清楚你说的是假设用户还是实际用户。我们说的是实际用户,我们知道在大型数据库中添加列是一个非常困难的问题,这就是为什么我们想换成非常小的桌子,但我们真的不知道这是不是一个好主意