我有一个相当大的表(~6 GB),我在这个查询上遇到了性能问题:
SELECT f.*,
TIME_FORMAT(f.scheme, '%H:%i') as scheme,
TIME_FORMAT(f.actual, '%H:%i') as actual,
DATE_FORMAT(f.flight_date, '%d-%m-%Y') as flight_date_formatted,
a.iata
FROM flights_database f
LEFT JOIN airports a ON f.airport = a.airportNameClean
WHERE f.flight_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY)
AND DATE_ADD(CURDATE(), INTERVAL 2 DAY)
AND (f.flight_number LIKE 'New York%' OR f.airport LIKE 'New York%' OR f.airline LIKE 'New York%')
ORDER by f.flight_date DESC, f.flight_scheme DESC
LIMIT 50"
我已使用EXPLAIN
并确定了这些潜在问题
我在flight_date, flight_number, airport, airline, scheme
上有一个索引,并报告使用它。
但是这个查询仍然需要大约30秒,这当然太多了。
使用某种子查询来替换OR部分可能会有所帮助。但是,如何确定在运行子查询后我实际需要搜索的搜索查询类型(例如哪一列)。
赞赏的想法和提示。
答案 0 :(得分:1)
我认为您当前的索引不是查询的最佳选择,主要是因为'或'表达式。你应该创建3个索引。
(flight_number,flight_date,schema)
(机场,flight_date,架构)
(航空公司,flight_date,架构)
然后更改查询以使用三个索引。您也可以稍微玩一下,也可以通过添加订单来修剪每个子查询,并限制为50。
select flight.*,
TIME_FORMAT(flight.scheme, '%H:%i') as scheme,
TIME_FORMAT(flight.actual, '%H:%i') as actual,
DATE_FORMAT(flight.flight_date, '%d-%m-%Y') as flight_date_formatted,
a.iata
from (
select *
from (
select f.Id,
f.flight_date,
f.schema
from flights_database f
where f.flight_date between DATE_SUB(CURDATE(), INTERVAL 30 DAY)
and DATE_ADD(CURDATE(), INTERVAL 2 DAY)
and f.flight_number like 'New York%'
order by f.flight_date desc,
f.schema desc limit 50
union
select f.Id,
f.flight_date,
f.schema
from flights_database f
where f.flight_date between DATE_SUB(CURDATE(), INTERVAL 30 DAY)
and DATE_ADD(CURDATE(), INTERVAL 2 DAY)
and f.airline like 'New York%'
order by f.flight_date desc,
f.schema desc limit 50
union
select f.Id,
f.flight_date,
f.schema
from flights_database f
where f.flight_date between DATE_SUB(CURDATE(), INTERVAL 30 DAY)
and DATE_ADD(CURDATE(), INTERVAL 2 DAY)
and f.airport like 'New York%'
order by f.flight_date desc,
f.schema desc limit 50
) f1
order by f1.flight_date desc,
f.schema desc limit 50
) f2
inner join flights_database flight on f2.Id = flight.Id
left join airports a on flight.airport = a.airportNameClean;
目前您的或声明将扩展为: [flight_date,flight_number],[flight_date,航空公司],[flight_date,airport]
因此,当优化器查看您的索引时,它将匹配 [flight_date,flight_number]到你当前的索引[flight_date,flight_number,机场,航空公司,方案](请注意他们如何开始相同),但是当遇到[flight_date,airline]时,没有与此表达式匹配的索引。因此优化器将确定它需要进行索引扫描或表扫描。然后它会再次遇到[flight_date,airport]它会确定这需要索引扫描或表扫描。
使用三个新索引和新查询,它会将三个索引与三个条件匹配,并确定每个索引都需要索引搜索(希望如此)。然后我们包括'scheme'来保存符合条件的所有行的id的行查找。