全文和左连接的慢查询

cj3*_*333 5 mysql full-text-search select

我有3张桌子

  • 约 250,000 条记录。
  • table1 是 MyISAM,添加带有标题和内容的 fullindex,添加带有 pid 的索引。
  • table2 和 table3 是 InnoDB,用 pid 添加索引。

只查询table3,只需要0.04秒。

select * from table3 
WHERE MATCH (title,content)
AGAINST ('+words' IN BOOLEAN MODE)
ORDER BY pid
Run Code Online (Sandbox Code Playgroud)

但是像这样查询,花费 16.87 秒。

SELECT * 
FROM table1
INNER JOIN table2 ON table1.pid = table2.pid
LEFT JOIN table3 ON table1.pid = table3.pid
WHERE MATCH (table3.title, table3.content)
AGAINST ('+words' IN BOOLEAN MODE)
ORDER BY table3.pid
Run Code Online (Sandbox Code Playgroud)

我为第二个查询制定了一个解释计划,返回:

id select_type  table     type  possible_keys    key    key_len    ref               rows      Extra
1  SIMPLE       table1    ALL    pid             NULL   NULL       NULL              201497    Using temporary; Using filesort
1  SIMPLE       table2    ref    pid             pid    32         mydb.table1.pid   1     
1  SIMPLE       table3    ref    pid             pid    32         mydb.table2.pid   222309    Using where
Run Code Online (Sandbox Code Playgroud)
  • 为什么第二个查询很慢?
  • 我该如何优化它?

谢谢。

Rol*_*DBA 6

不幸的是,MySQL 的行为完全符合我的预期。

问题在于 MySQL 的查询优化器在与 EXPLAIN 计划的编译中的其他表结合使用时会变得非常混乱。我之前写过这个:

我的建议:尝试通过在 JOIN 之前进行 FULLTEXT 搜索来重构查询

SELECT * FROM table1 
INNER JOIN table2 ON table1.pid = table2.pid 
LEFT JOIN
(
    select * from table3  
    WHERE MATCH (title, content) 
    AGAINST ('+words' IN BOOLEAN MODE )
    ORDER BY pid 
) table3
ON table1.pid = table3.pid 
;
Run Code Online (Sandbox Code Playgroud)