我正在开发一个大型内容网站,其中包含一个“内容”表,其中包含超过5000万条记录。这是表结构:
contain id(INT11 INDEX),
name(varchar150 FULLTEXT),
description (text FULLTEXT),
date(INT11 INDEX)
我想在此内容中添加“标签”。
我认为有两种方法:
在表格内容中创建一个varchar(255 FULLTEXT)“tags”列。存储由逗号分隔的所有标签,并使用MATCH&amp ;;逐行搜索(我认为这将是慢的)。 AGAINS。
制作2张桌子。第一个表名“tags”包含列id,tag(varchar(30 INDEX或FULLTEXT?)),“contents_tags”包含id,tag_id(int11 INDEX)和content_id(int11 INDEX)以及通过3个表的JOINS搜索内容(内容) - contents_tags - tags)检索带有标签的所有内容。
我认为这是一个缓慢的记忆杀手,因为50M的狂热联接 table * contents_tags * tags。
存储标签以使其尽可能高效的最佳方法是什么?什么是通过文本搜索的最快方式(例如“movie 3d 2011”和简单标记“视频”)以及查找内容。?
桌子的大小(现在大约5Gb没有标签)。该表是MYISAM,因为我需要将FULLTEXT中表格内容的名称和描述存储到字符串搜索(用户现在通过这些字段搜索),并且需要以标签搜索的最佳速度。
有没有经验?
谢谢!
答案 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字段是一个非常糟糕的主意,从不在数据库中使用。