【问题标题】:Proper mysql datastructure for a fulltext search用于全文搜索的正确 mysql 数据结构
【发布时间】:2010-01-25 09:47:00
【问题描述】:

希望有人可以提供一些mysql建议...

我有 2 个如下所示的表:

searchTagsTable
    ID
    tag

dataTable
    ID
    title
    desc
    tagID

所以“dataTable”中的“tagID”列是一个以逗号分隔的 id 字符串,指向 searchTagsTable。

我想使用 mysql 内置的全文搜索功能来搜索标题、描述和标签。

我想知道:在这种情况下,什么被认为是“最佳”解决方案?

我应该让数据结构保持原样吗?如果是这样,我应该如何构造 sql 以允许对所有三列进行全文搜索 - 标题、描述和标签?

或者最好去掉keywordsTable,并在dataTable的“tags”列中用逗号分隔实际标签?

提前感谢您的帮助。

特拉维斯

【问题讨论】:

    标签: mysql search full-text-search


    【解决方案1】:

    我应该让数据结构保持原样吗?如果是这样,我应该如何构造 sql 以允许对所有三列进行全文搜索 - 标题、描述和标签?

    那是不可能的。索引只能跨越单个表的列。

    或者最好去掉keywordsTable,并在dataTable的“tags”列中用逗号分隔实际标签?

    这肯定是最简单的解决方案。您目前并没有真正从为标签提供自己的身份中获得任何好处,因为您不能使用外键并对其进行索引。

    然而,MySQL 的 FULLTEXT 索引对于标签系统来说并不理想:

    • 默认情况下,它不会索引短于四个字母的单词;
    • 默认情况下,它有很多(很多)停用词,它不会索引您可能想要用于标签的停用词;
    • 它的效率会低于普通索引;
    • 它只在 MyISAM 中有效,在所有其他方面,它都是比 InnoDB 差得多的数据库引擎。除非您确实必须这样做,否则您今天不应该真正使用 MyISAM。

    您可以通过更改 MySQL 配置来修复最小字长和停用词。不过,这将使您的索引更大。如果您在将要部署您的应用程序的任何地方都控制数据库,并且如果您仅在全文搜索素材中使用标签作为“额外词”而不是完整的分类系统,那么这可能是一个可接受的解决方案。

    否则...数据库中以逗号分隔的任何内容都是可疑的 IMO。通常最好使用一对多连接表来表达一个实体有很多标签的想法。然后,您可以使用简单的索引来帮助查找,而不是有限的 FULLTEXT 索引方案,这将更快、更可靠,并允许您使用 InnoDB 和外键。例如:

    dataTable
        ID       (primary key)
        title
        desc
    
    dataTags
        ID       (foreign key -> dataTable)
        tagName  (index this column)
    

    (如果您希望标签具有独立身份,您仍然可以在此基础上使用 tagID->tagName 映射。不过我不确定它是否对您的情况有用。)

    如果您需要从上述一对多关系中获取逗号分隔的列表,您可以使用 MySQL 特定的 GROUP_CONCAT 函数来完成。

    SELECT dataTable.*, GROUP_CONCAT(dataTags.tagName)
    FROM dataTable
    JOIN dataTags ON dataTags.ID=dataTable.ID
    GROUP BY dataTable.ID;
    

    剩下的就是标题和描述的全文索引。不幸的是,这确实需要您将它们放在 MyISAM 表中。

    您可能还考虑将“规范”副本保留在主表中(可能在 ACID 安全的 InnoDB 表中),并存储所有标题、说明和标签的单独副本一起放在一个全文索引的 MyISAM 表中,纯粹是为了全文搜索。这确实意味着每次更改主数据时都必须进行额外更新(尽管如果您失败或必须回滚事务,至少现在错误的只是相对不重要的搜索诱饵),但优点是您可以申请对其进行额外处理,例如词干和标点处理,而 MySQL 的 FULLTEXT 索引器不会自行处理。

    【讨论】:

    • 感谢详细的回复,很有帮助。关于这一点:“通常最好使用一对多连接表来表达一个实体有很多标签的想法。”请多多包涵。我想确定我理解您建议的表 dataTable 和 dataTags 之间的关系。假设我在 dataTable (ID 1, ID 2) 中有两个不同的行,我想将它们与特定标签“mysql”相关联。你能解释一下表 dataTags 中的数据是什么样的吗?再次感谢您的帮助,非常感谢。特拉维斯
    • 是的,您将拥有 dataTags (ID, tagName)(1, 'mysql')(2, 'mysql')ID 只是返回到dataTable 的外键,本身不是主键。主键将在 ID 和 tagName 上。
    • 太棒了。谢谢你的帮助。 -特拉维斯
    猜你喜欢
    • 1970-01-01
    • 2016-04-30
    • 2018-10-12
    • 2013-02-04
    • 1970-01-01
    • 1970-01-01
    • 2015-02-28
    • 2016-04-05
    相关资源
    最近更新 更多