mysql - MySQL 中的文本搜索 - 性能和替代方案

标签 mysql sql lucene indexing full-text-search

我在 MySQL 中有一组这样的表(由 [table_name]_id 引用的外键):

Articles(id, author_id, title, date, broad_search, ...)
Keywords(id, article_id, keyword (varchar))
Authors(id, name, ...)
Attachments(id, article_id, url, ...)

我们最关心的表是“关键字”,所以我只提及它的索引:

id - Primary - BTREE
(article_id,keyword) - Unique - BTREE
keyword - BTREE
article_id - BTREE

每篇文章都有关联的关键字列表。 Articles 中的“broad_search”列说明该特定文章是否可以与关键字广泛匹配 (broad_search=1),或者是否必须与关键字完全匹配 (broad_search=0)。我有一个 SELECT 查询,它根据关键字、broad_search 参数和其他过滤条件提取文章列表。

$sql = "SELECT *
FROM Keywords k, Attachments at, Articles ar, Authors a (2 more tables)
WHERE 
((ar.broad_search=0 AND k.keyword = '$Keyword')
OR (ar.broad_search=1 AND (INSTR('$Keyword', k.keyword)>0 OR k.keyword like '%$Keyword%')))
AND at.article_id = ar.id
AND a.id = ar.author_id 
... (more conditions)
LIMIT 20";

一篇文章可以设置为布拉德匹配或完全匹配,我正在尝试根据关键字获取它们的列表。

精确匹配很简单。但广泛匹配有多种情况,不允许我使用像“%search_term%”这样的简单通配符模式。一个例子:

Keywords for a broad match article = {books, used books, reading books, popular book}
search term = new books

现在,我们不能使用 mysql 通配符字符串匹配,因为 '%new books%' 不会匹配任何关键字,但需要检索它,因为搜索项包含关键字的子字符串(广泛搜索=1)。因此,broad_search 有 2 种类型:关键字“二手车”中的 search_term =“汽车”和关键字“汽车”中的搜索项 =“二手车”。

如果 Broad_search=0,则进行完全匹配。如果broad_search=1,则匹配两种情况:

 ((ar.broad_search=0 AND k.keyword = '$Keyword')
        OR (ar.broad_search=1 AND (INSTR('$Keyword', k.keyword)>0 OR k.keyword like '%$Keyword%')))

我编写的查询完美地完成了这项工作。但问题在于性能。关键字表非常大,有 100,000 多行,并且还在不断增长。此外,这是一个高负载应用程序,由于收到大量请求,它会杀死我的服务器。

我觉得这不是执行文本搜索的正确方法。我尝试浏览有关全文搜索的 mysql 文档,但我不太了解它的应用程序以及它是否符合我的搜索条件。另外,我在想 Apache Lucene 是否是一个更好的选择,但我之前没有使用过它,所以不太确定(此查询在 PHP 脚本中运行)。

我应该如何实现这个?是索引问题,还是 MySQL INSTR 函数效率低下,或者我应该使用完全不同的方法?

最佳答案

MySQL不是搜索引擎,它是关系数据库管理系统(RDBMS)。但是,您可以实现 native MySQL 工具来模拟全文搜索功能,例如将搜索表设置为 MyISAM 并向您希望搜索的列添加 FULLTEXT 索引。您可以阅读MySQL docs有关 MySQL 如何支持全文搜索的更多信息。

即使您按照您想要的方式获得全文搜索查询,您仍然会错过真正的搜索引擎 (Lucene) 支持的大量功能。诸如构面、空间搜索、结果增强、加权等功能。我建议您阅读 Apache SOLR ,因为它支持所有这些功能以及更多功能。甚至还有一个PHP SOLR API您可以使用它来访问 SOLR 实例。

我并不是说完全放弃 MySQL,而是将其用于其预期目的,持久存储可查询的数据,并可用于填充搜索引擎索引。 SOLR 甚至有一个内置的文档导入处理程序,当您想要从 MySQL 数据库批量导入数据时,它允许您设置要使用的数据库查询。

与学习大多数新技术一样,学习曲线相对较高,但是当您完成后,您会想知道如果不使用真正的全文搜索引擎,您是如何度过的。

关于mysql - MySQL 中的文本搜索 - 性能和替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8981039/

相关文章:

java - hibernate 搜索,现有数据不可搜索

php - Mysql 内连接在 Mysql 5.1 上不起作用

mysql - 使用自动递增主键插入到 View 中?

mysql - Docker MYSQL 容器随卷立即退出

mysql - SQL:用子查询打破平局

带有 SELECT 状态的 SQL INNER JOIN 抛出错误

php - mysql 值转为 html 形式

mysql - 使用sql提交的正确方法

java - 为什么在 Lucene 4,1 分析器中使用 MappingCharFilter 会破坏通配符匹配

java - 如何将 Wordnet 同义词与 Hibernate 搜索结合使用?