我遇到了一个嵌套查询的严重问题,我怀疑MySQL将其解释为相关的子查询,而实际上它应该是不相关的。查询跨越两个表,一个是产品列表,另一个是不同时间点的价格。我的目标是返回在整个时间内价格范围超过一定值的产品的每个价格记录。我的查询如下:
SELECT oP.id, oP.title, oCR.price, oC.timestamp
FROM Crawl_Results AS oCR
JOIN Products AS oP
ON oCR.product = oP.id
JOIN Crawls AS oC
ON oCR.crawl = oC.id
WHERE oP.id
IN (
SELECT iP.id
FROM Products AS iP
JOIN Crawl_Results AS iCR
ON iP.id = iCR.product
WHERE iP.category =2
GROUP BY iP.id
HAVING (
MAX( iCR.price ) - MIN( iCR.price )
) >1
)
ORDER BY oP.id ASC
单独来看,内部查询执行良好,并返回价格范围高于标准的产品的id列表。如果我在in子句中提供一个简单的id列表,那么外部查询也可以正常工作。然而,当我一起运行它们时,查询需要大约3分钟才能返回大约1500行,所以我认为它对外部的每一行都执行内部查询,这并不理想。我确实在内部和外部查询中对列进行了相同的别名,所以我认为如上所述在内部和外侧对它们进行不同的别名会解决问题,但事实并非如此。
你知道这里发生了什么吗?
MySQL可能认为可以使用索引来更快地执行查询,方法是为每个OP.id
运行一次。首先要检查的是你的统计数据是否是最新的。
您可以将where ... in
重写为筛选inner join
。这不太可能针对搜索进行"优化":
SELECT *
FROM Crawl_Results AS oCR
JOIN Products AS oP
ON oCR.product = oP.id
JOIN Crawls AS oC
ON oCR.crawl = oC.id
JOIN (
SELECT iP.id
FROM Products AS iP
JOIN Crawl_Results AS iCR
ON iP.id = iCR.product
WHERE iP.category =2
GROUP BY
iP.id
HAVING (MAX(iCR.price) - MIN(iCR.price)) > 1
) filter
ON OP.id = filter.id
另一种选择是使用临时表。您将子查询的结果存储在一个临时表中,并对其进行联接。这确实迫使MySQL不要将子查询作为相关查询来执行。