【问题标题】:Best way to store "tags" for speed in enormous table在巨大的桌子上存储“标签”以提高速度的最佳方式
【发布时间】:2011-11-08 22:50:37
【问题描述】:

我正在开发一个大型内容网站,其中包含一个“内容”表,其中包含超过 5000 万条记录。这是表结构:

contain id(INT11 INDEX), 
name(varchar150 FULLTEXT), 
description (text FULLTEXT), 
date(INT11 INDEX)

我想给这些内容添加一个“标签”。

我认为有两种方法:

  1. 在表格内容中创建一个 varchar(255 FULLTEXT)“标签”列。存储以逗号分隔的所有标签,并使用 MATCH & AGAINS 逐行搜索(我认为这会很慢)。

  2. 制作 2 张桌子。第一个表名“tags”与列 id、tag(varchar(30 INDEX 或 FULLTEXT?))、“contents_tags”与 id、tag_id (int11 INDEX) 和 content_id (int11 INDEX) 并通过 3 个表的 JOINS (contents - contents_tags - tags) 以检索带有标签的所有内容。

我认为这是缓慢且内存杀手,因为 50M 的 ENORMOUS JOIN 表 * contents_tags * 标签。

存储标签以使其尽可能高效的最佳方法是什么?按文本搜索(例如“movie 3d 2011”和简单标签“video”)并定位内容的最快方法是什么?

表的大小(现在大约 5Gb,没有标签)。该表是一个MYISAM,因为我需要将FULLTEXT中的表内容的名称和描述存储到字符串搜索(用户现在可以通过此字段搜索),并且需要通过标签搜索的最佳速度。

有这方面的经验吗?

谢谢!

【问题讨论】:

  • 如果您使用(唯一)键加入((eq_)ref join),您的巨大的加入将不会那么庞大。试试吧,这就是要走的路。
  • @Konerak 应该是回答,而不是评论

标签: php mysql database performance


【解决方案1】:

FULLTEXT 索引并没有你想象的那么快。

使用单独的表来存储您的标签:

Table tags
----------
id integer PK
tag varchar(20)

Table tag_link
--------------
tag_id integer foreign key references tag(id)
content_id integer foreign key references content(id)
/* this table has a PK consisting of tag_id + content_id */

Table content
--------------
id integer PK
......

您使用以下命令选择带有标签 x 的所有内容:

SELECT c.* FROM tags t
INNER JOIN tag_link tl ON (t.id = tl.tag_id)
INNER JOIN content c ON (c.id = tl.content_id)
WHERE tag = 'test'
ORDER BY tl.content_id DESC /*latest content first*/
LIMIT 10;

由于有外键,tag_links 中的所有字段都被单独索引。
`WHERE tags = 'test' 选择 1 (!) 记录。
使用 10,000 个标记链接等值加入。
并且 Equi-join that 每个都有 1 个内容记录(每个 tag_link 只指向 1 个内容)。
由于限制为 10,所以 MySQL 一有 10 个项目就会停止查找,所以它实际上只查看 10 个 tag_links 记录。
content.id 是自动递增的,因此较大的数字可以非常快速地代理较新的文章。

在这种情况下,您从不需要寻找除相等以外的任何内容,并且您从 1 个标签开始,您使用整数键等值连接(可能的最快连接)。

没有if-thens-or-buts,这是最快的方法。

请注意,由于标签最多只有几 1000 个,因此任何搜索都会比钻研完整的目录快得多。

终于
CSV 字段是一个非常糟糕的主意,永远不要在数据库中使用。

【讨论】:

  • 好的,我明白了,另一个问题是,将标签名称存储在表“tags”、varchar(XX) 但 BTREE INDEX 或 FULLTEXT 中的最佳方法是什么?
  • tagtag_link 表最好使用 InnoDB,即 BTREE 索引和 varchar(x)。尽量减少字段的长度,它会加快速度,标签不需要 255。
猜你喜欢
  • 2011-09-14
  • 2012-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-23
  • 2011-04-02
  • 2012-03-05
  • 2021-04-13
相关资源
最近更新 更多