设计一个严重非规范化的表格,如“喜欢”

时间:2012-02-09 16:25:57

标签: mysql denormalization

我目前正在构建一个具有多种用户类型的Web应用程序,用户可以参与多种活动类型。

我需要设计一个表格,将用户和活动之间的“喜欢”(赞成票,+ 1,等等)联系起来。无论如何我都不是不是的MySQL专家,所以我想避免使用我的数据库设计走错路,特别是这样的事情。

我在想的是如下表:

CREATE TABLE likes (
  from_id int(11) NOT NULL,
  from_type VARCHAR(100) NOT NULL,
  to_id int(11) NULL,
  to_type VARCHAR(100) NULL,
  posted TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY(from_id, from_type, to_id, to_type),
  INDEX(from_id, from_type),
  INDEX(to_id, to_type)
)Engine=InnoDB;

随着系统扩展,这会带来什么性能问题?这些“喜欢”将在新闻Feed中使用,因此会有很多的读写操作。

有没有一种我没想过的更好的方法?

提前致谢!

1 个答案:

答案 0 :(得分:4)

你的from_typeto_type字段,如VARCHAR(100),将是一个巨大的空间浪费,与它们的匹配将不会像匹配,例如,整数from_type_idto_type_id。当您向表中添加更多条目时,它们也会使索引的维护速度变慢。

如果您需要一个人类可读的类型名称,请创建另一个列出它们的表及其数字ID。您可以将id作为该表的外键,尽管维护外键的完整性会产生一些成本。

可能不会有太多类型,至少与表中的行数相比,所以任何需要它们的进程都可以只读取该表一次,而不是询问数据库与每次读取都进行连接。

关于索引:

这些将会减慢插入速度。您的目标应该是为了满足所有读取查询的要求,并尽可能地使您所做的那些查询。

多列索引肯定是有用的,并且它们具有良好的属性,即所有前缀基本上都被索引。也就是说,如果您在(a, b, c)上有索引,那么它也可以用作(a, b)上的索引,甚至只能用在a上。 (并且MySQL 以这种方式使用索引)。

这意味着,因为你有一个索引

(from_id, from_type, to_id, to_type)

然后你还需要

上的索引
(to_id, to_type)

但你可以消除

上的索引
(from_id, from_type)

使数据库单独维护该索引只会降低它的速度。

这也意味着您可能需要预先考虑索引中列的顺序。将type置于id之前可能更有意义,因为您更有可能在数据库中查询特定类型的所有喜欢,而不是来自特定ID的所有喜欢(对于每种类型)。 / p>

如果您构建索引,请执行以下操作:

(to_type, to_id, from_type, from_id)
(from_type, from_id)

然后您可以有效地搜索:

  • 所有人都喜欢从类型(from_type)
  • 的所有对象中发起
  • 所有人都喜欢从特定对象(from_type, from_id)
  • 发起
  • 所有喜欢针对(to_type)
  • 类型的所有对象
  • 所有喜欢针对特定对象(to_type, to_id)
  • (有趣的是)所有喜欢来自针对特定对象的特定类型(例如,所有'人',喜欢这个特定的'文章') (to_type, to_id, from_type)
  • 最后,您对所有四个(to_type, to_id, from_type, from_id)
  • 都有唯一性限制