首页 文章

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

提问于
浏览
2

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

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

我想为这个内容添加一个“标签” .

我想2种方法:

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

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

我认为这是一个缓慢和记忆杀手,因为50M表* contents_tags *标签的ENORMOUS JOIN .

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

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

有经验吗?

谢谢!

1 回答

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

    在这种情况下,你需要寻找除了相等之外的任何东西,然后从1个标签开始,你使用整数键进行等分连接(可能是最快的连接) .

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

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

    Finally
    CSV字段是一个非常糟糕的主意,从不在数据库中使用 .

相关问题