我有两个运行速度非常快的 MySQL 查询,但是当我组合它们时,新查询非常慢。
快速(<1 秒,15 个结果):
SELECT DISTINCT
Id, Name, Company_Id
FROM people
where Company_Id in (5295, 1834)
and match(Locations) against('austin')
快速(<1 秒,2970 个结果):
select distinct Company_Id from technologies
where match(Name) against('elastic')
and Company_Id is not null
当我像这样将两者结合起来时:
SELECT DISTINCT Id, Name, Company_Id
FROM people
where Company_Id in
( select Company_Id from technologies
where match(Name) against('elastic')
and Company_Id is not null
)
and match(Locations) against('austin')
结果查询需要 2 多分钟才能完成。它命中了 278 行。
我已经尝试用几种方法重写慢速查询。另一个例子是这样的:
SELECT DISTINCT
`Extent1`.`Id`, `Extent1`.`Name`, `Extent1`.`Company_Id`
FROM `people` AS `Extent1`
INNER JOIN `technologies` AS `Extent2`
ON (`Extent1`.`Company_Id` = `Extent2`.`Company_Id`)
WHERE (`Extent1`.`Company_Id` IS NOT NULL)
AND ((match(`Extent1`.`Locations`) against('austin'))
AND (match(`Extent2`.`Name`) against('elastic')))
我在 Windows 上使用 MySQL 5.7。我在名称和位置列上有全文索引。我的 InnoDB 缓冲区使用率从未超过 40%。我尝试使用 MySQL Workbench 查看执行计划,但它显示“Explain data not available for statement”
如果您看到任何我可以改进或尝试的地方,请告诉我。谢谢。
最佳答案
IN ( SELECT ... )
优化不佳,至少在旧版本的 MySQL 中是这样。您使用的是什么版本?
使用 FULLTEXT
时索引 ( MATCH...
),如果可能,该部分首先执行。这是因为 FT 查找几乎总是比其他任何事情都快。
但是当使用两个全文查询时,它会选择一个,然后不能对另一个使用全文。
这是一种可能的解决方法:
- 有一个额外的搜索表。它包括
Name
和Locations
- 有
FULLTEXT(Name, Locations)
-
MATCH (Name, Locations) AGAINST ('+austin +elastic' IN BOOLEAN MODE)
如有必要,AND
用一些东西来验证它不是,例如,找到一个叫“奥斯汀”的人。
另一种可能性:
5.7(或 5.6?)可能能够通过在子查询上创建索引来优化它:
SELECT ...
FROM ( SELECT Company_Id FROM ... MATCH(Name) ... ) AS x
JOIN ( SELECT Company_Id FROM ... MATCH(Locations) ... ) AS y
USING(Company_id);
提供 EXPLAIN
;我希望看到 <auto-key>
.
测试一下。如果它“快”,那么您可能需要添加另一个 JOIN
和/或 WHERE
. (我不清楚您的最终查询需要是什么。)
关于结合两个非常快的查询时MySQL慢查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42097593/