在巨大的表格中存储速度“标签”的最佳方式

时间:2011-09-02 06:45:10

标签: php mysql database performance

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

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

我想在此内容中添加“标签”。

我认为有两种方法:

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

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

  3.   

    我认为这是一个缓慢的记忆杀手,因为50M的狂热联接   table * contents_tags * tags。

    存储标签以使其尽可能高效的最佳方法是什么?什么是通过文本搜索的最快方式(例如“movie 3d 2011”和简单标记“视频”)以及查找内容。?

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

    有没有经验?

    谢谢!

1 个答案:

答案 0 :(得分:7)

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(!)记录 Equi-join加上10,000个taglinks Equi-join 每个都有1个内容记录(每个tag_link只指向1个内容)。
由于限制10,MySQL会在有10个项目后立即停止查看,因此它实际上只查看10个tag_links记录。
content.id是自动增量,因此较高的数字是新文章的快速代理。

在这种情况下,你从不需要寻找除了相等之外的任何东西,并且你开始使用整数键等同加入的1个标记(可能是最快的连接)。

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

请注意,因为最多只有1000个标签,所以任何搜索都会比在完整内容表中钻取快得多。

<强>最后
CSV字段是一个非常糟糕的主意,从不在数据库中使用。