适用于全文搜索的mysql数据结构

时间:2010-01-25 09:47:01

标签: mysql search full-text-search

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

我有两个看起来像这样的表:

searchTagsTable
    ID
    tag

dataTable
    ID
    title
    desc
    tagID

因此“dataTable”中的“tagID”列是一个逗号分隔的指向searchTagsTable的ID字符串。

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

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

我应该保留数据结构吗?如果是这样,我应该如何构造sql以允许全文搜索所有三列 - title,desc和tag?

或者最好只删除keywordsTable,并在dataTable的“tags”列中以逗号分隔实际标记?

提前感谢您的帮助。

特拉维斯

1 个答案:

答案 0 :(得分:0)

  

我应该保留数据结构吗?如果是这样,我应该如何构造sql以允许全文搜索所有三列 - title,desc和tag?

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

  

或者最好只删除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;

留下标题和desc的全文索引。不幸的是,您需要将它们放在MyISAM表中。

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