这个 MySQL 查询工作得很好
SELECT o.id
FROM descriptions_programs d, titles_programs t, programs o
WHERE (d.object_id=o.id
AND MATCH (d.text) AGAINST ('+china' IN BOOLEAN MODE)
AND d.current=1)
AND (t.object_id=o.id
AND MATCH (t.text) AGAINST ('+china' IN BOOLEAN MODE)
AND t.current=1)
但如果我用 OR 替换 AND,则查询会运行很长时间。 (我必须杀掉它。):
SELECT o.id
FROM descriptions_programs d, titles_programs t, programs o
WHERE (d.object_id=o.id
AND MATCH (d.text) AGAINST ('+china' IN BOOLEAN MODE)
AND d.current=1)
OR (t.object_id=o.id
AND MATCH (t.text) AGAINST ('+china' IN BOOLEAN MODE)
AND t.current=1)
为什么是这样?不要沉迷于 +china 的简单性。我只是为了调试而简化了它。另外,如果我只运行 MATCH AGAINST 测试之一,它工作得很好,所以两者本身都没有问题。我感觉到我无意中通过使用 OR 造成了巨大的连接,但我就是不明白。我之前对两个子选择的 UNION 使用了 n IN 测试,该测试有效,但这也应该有效。正确的?
Update:根据鲍比斯的要求。它不是超级慢,但大约 500 毫秒,它几乎不如使用 UNION 快在这里讨论 https://stackoverflow.com/questions/668371/mysql-fulltext-search-across-1-table.
mysql> explain SELECT o.id
-> FROM programs o
-> JOIN titles_programs t ON t.object_id=o.id
-> JOIN descriptions_programs d ON d.object_id=o.id
-> WHERE MATCH (d.text) AGAINST ('+china' IN BOOLEAN MODE) AND d.current=1
-> OR MATCH (t.text) AGAINST ('+china' IN BOOLEAN MODE) AND t.current=1
-> ;
+----+-------------+-------+-------+
----------------+----------------+---------+----------------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+----------------+----------------+---------+----------------------+--------+-------------+
| 1 | SIMPLE | o | index | PRIMARY | PRIMARY | 4 | NULL | 148666 | Using index |
| 1 | SIMPLE | d | ref | object_current | object_current | 4 | haystack.o.id | 1 | |
| 1 | SIMPLE | t | ref | object_current | object_current | 4 | haystack.d.object_id | 1 | Using where |
+----+-------------+-------+-------+----------------+----------------+---------+----------------------+--------+-------------+
杰森的回答很正确。此外,我会尝试使用更现代的 ANSI 连接语法来减轻 WHERE 子句的负担,从而缓解那里的混乱:
SELECT o.id
FROM programs o
JOIN titles_programs t ON t.object_id=o.id
JOIN descriptions_programs d ON d.object_id=o.id
WHERE MATCH (d.text) AGAINST ('+china' IN BOOLEAN MODE) AND d.current=1
OR MATCH (t.text) AGAINST ('+china' IN BOOLEAN MODE) AND t.current=1
这将阻止意外的交叉连接导致组合爆炸;我希望它能够在合理的时间内运行,除非数据库真的很大。
如果没有,您可以发布上述 EXPLAIN SELECT 的结果吗?据推测,一个或两个全文索引都没有被使用。我当然可以想象查询优化器无法使用第二个全文索引,通过尝试“填充”与第一个全文查询不匹配的行而不是直接进入索引之类的操作。
通常,当您想要对两列组合进行全文索引时,您可以在两列上创建一个索引。无论如何,这会快得多。然而,这意味着您必须将标题和描述放在同一个表中。这可能不是那么困难:因为全文仅适用于 MyISAM 表(并且您通常不希望 MyISAM 表中的规范数据),您可以将数据的最终副本保留在正确规范化的 InnoDB 表中,并使用附加的 MyISAM 表只包含被剥离和阻止的搜索诱饵。
如果这些都没有什么好处......好吧,我想我会回到你提到的 UNIONing,再加上应用程序级过滤器来删除重复的 ID。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)