MySQL FULLTEXT搜索> 1表

时间:2009-03-20 23:42:00

标签: mysql full-text-search

作为this question的更一般情况,因为我认为可能会让更多人感兴趣...在两个表上执行全文搜索的最佳方法是什么?假设有三个表,一个用于程序(带有submitter_id),另一个用于带有object_id的标签和描述:外键引用程序中的记录。我们希望程序的submitter_id在其标签或描述中包含某些文本。我们必须使用MATCH AGAINST,因为我不会在这里讨论。不要挂在这方面。

programs
  id
  submitter_id
tags_programs
  object_id
  text
descriptions_programs
  object_id
  text

以下工作并在20ms左右执行:

SELECT p.submitter_id
FROM programs p
WHERE p.id IN
    (SELECT t.object_id
    FROM titles_programs t
    WHERE MATCH (t.text) AGAINST ('china')
UNION ALL
    SELECT d.object_id
    FROM descriptions_programs d
    WHERE MATCH (d.text) AGAINST ('china'))

但是我尝试将其重写为JOIN,如下所示,它运行了很长时间。我必须在60秒后杀死它。

SELECT p.id 
FROM descriptions_programs d, tags_programs t, programs p
WHERE (d.object_id=p.id AND MATCH (d.text) AGAINST ('china'))
OR    (t.object_id=p.id AND MATCH (t.text) AGAINST ('china'))

出于好奇,我用AND取代了OR。这也在几毫秒内运行,但这不是我需要的。上面的第二个查询出了什么问题?我可以和UNION以及子选择一起生活,但我想了解。

4 个答案:

答案 0 :(得分:5)

在过滤器后加入(例如加入结果),不要尝试加入然后过滤。

原因是您没有使用全文索引。

回应评论时的澄清:我在这里使用了一般性联合词,而不是JOIN,而是作为合并或组合的同义词。

我基本上说你应该使用第一个(更快的)查询,或类似的东西。它更快的原因是每个子查询都足够整洁,db可以使用该表的全文索引来非常快速地进行选择。加入两个(可能是更小的)结果集(使用UNION)也很快。这意味着整件事情很快。

慢速版本通过大量数据进行测试,以测试它是否符合您的要求,而不是快速下载数据并仅搜索您可能真正想要的行。

答案 1 :(得分:1)

以防您不知道:MySQL有一个名为EXPLAIN的内置语句,可用于查看表面下发生的情况。有很多关于此的文章,所以我不会详细介绍任何细节,但是对于每个表,它提供了对它需要处理的行数的估计。如果您查看第二个查询的EXPLAIN结果中的“rows”列,您可能会看到行数非常大,当然比第一个查询要大很多。

网上充满了关于在MySQL中使用子查询的警告,但事实证明,开发人员很多时候比MySQL优化器更聪明。在加入之前以某种方式过滤结果可能会在许多情况下导致性能提升。

答案 2 :(得分:0)

如果你加入两个表,你最终会有很多记录需要检查。举个例子,如果两个表都有100,000条记录,那么完全加入它们会给你10,000,000,000条记录(100亿!)。

如果您通过AND更改OR,那么您允许引擎过滤掉表description_programs中与'china'不匹配的所有记录,只有然后加入titles_programs。

无论如何,这不是你需要的,所以我建议你坚持使用UNION方式。

答案 3 :(得分:0)

工会是正确的方式。连接将同时拉入两个全文索引,并且可以实际执行多次检查。