【发布时间】:2022-01-26 17:48:57
【问题描述】:
我有一个查询,它包含两个布尔模式下的全文搜索(结合OR 运算符),在 MySQL 5.6 上运行良好,但在碰到 MySQL 5.7 版后失败。两个数据库都有完全相同的记录集,都托管在 AWS 上(InnoDB、aurora)。
下面的查询(不要太注意表/列名,因为我试图匿名):
SELECT
cars.id
FROM cars
INNER JOIN driver_licenses ON driver_licenses.car_id = cars.id
INNER JOIN drivers ON drivers.id = driver_licenses.driver_id AND drivers.noobie_driver = 0
WHERE (
(MATCH(cars.name) AGAINST ('mark*' IN BOOLEAN MODE))
OR (MATCH(drivers.first_name, drivers.last_name, drivers.email) AGAINST ('mark*' IN BOOLEAN MODE))
);
当然,我在 [first_name, last_name, email] 列上有全文索引,在 noobie_driver 上有一个 btree 索引。 cars.name 上有两个索引——一个是 btree,另一个是全文。
在升级之前,查询返回了正确的结果(以数百计,而总数为几百万条记录)。
升级后 - 查询/优化器似乎只关注第一个条件,完全忽略了第二个全文搜索(按驱动程序的姓名和电子邮件)并且只返回很少的记录 - 直接相关到cars.name的搜索结果。
单独运行查询(第一次针对cars.name,然后针对驱动程序详细信息)然后合并时,它们返回的结果与升级前相同。
此外,当我强制忽略 noobie_driver 索引(或删除 noobie_driver 条件)时,会同时考虑两个全文搜索条件。
在两个 DB 中运行 EXPLAIN 返回相同的结果。
+----+-------------+---------------------------+------------+--------+------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+-----------------------------------------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------------+------------+--------+------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+-----------------------------------------------------+------+----------+-------------+
| 1 | SIMPLE | drivers | NULL | ref | PRIMARY,index_drivers_on_noobie_driver | index_drivers_on_noobie_driver | 1 | const | 6798 | 100.00 | NULL |
| 1 | SIMPLE | driver_licenses | NULL | ref | index_driver_licenses_on_car_id,index_driver_licenses_on_driver_id | index_driver_licenses_on_driver_id | 5 | Rental.drivers.id | 1 | 100.00 | Using where |
| 1 | SIMPLE | cars | NULL | eq_ref | PRIMARY | PRIMARY | 4 | Rental.driver_licenses.car_id | 1 | 100.00 | Using where |
+----+-------------+---------------------------+------------+--------+------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+-----------------------------------------------------+------+----------+-------------+
明天我将着手重建索引/表,看看这是否会对 5.7 的行为带来任何改变,一旦完成,我会回来提供更多细节。在所有 3 个表上运行 OPTIMIZE TABLE 并没有解决任何问题。
我想知道:
- 我是否遗漏了一些东西,它现在是 5.7 中的一个功能,现在它的行为方式是这样的?
- 如何克服该问题并保持完全相同的查询(因此无需忽略索引或执行两个单独的查询以在之后组合结果)?
【问题讨论】:
-
解释计划在哪里?升级后您是否重建了索引?
-
@symcbean 我用 EXPLAIN 和信息更新了原始帖子,运行
OPTIMIZE TABLE后它的行为仍然相同