MySQL select in join 子句扫描太多行

Posted

技术标签:

【中文标题】MySQL select in join 子句扫描太多行【英文标题】:MySQL select in join clause scanning too many rows 【发布时间】:2012-09-27 09:03:29 【问题描述】:

好吧,伙计们,以下问题一直困扰着我:

我使用下面的查询来选择产品和价格的概览,包括基于另一个表(结果)中的字段 StartTime 的最新结果价格。为此,我认为我需要在连接中进行子选择。

问题在于 EXPLAIN 函数告诉我 mysql 正在扫描所有结果行(225000 行)而不使用任何索引。

有什么方法可以加快速度吗?最好通过添加 WHERE 语句让 mysql 只查看具有相应 pID 的行。

select p.pID, brandname, description, p.EAN, RetailPrice, LowestPrice, min(price), min(price)/lowestprice-1 as afwijking
from tproducts p
    join ( 
    select Max(tresults.StartTime) AS maxstarttime, tresults.pID
    from tresults
    -- maybe adding a where clause here?
    group by tresults.pID
    ) p_max on (p_max.pID = p.pID)
join tresults res on (res.starttime = p_max.maxstarttime and p.pID = res.pID and res.websiteID = 1)
join tsupplierproducts sp on (sp.pID = p.pID AND supplierID = 1)
join tbrands b on (b.brandID = p.BrandID)
group by p.pID, brandname, description, p.EAN, RetailPrice, LowestPrice

索引位于属于连接或 where 子句的所有列上。

任何帮助将不胜感激。谢谢!

【问题讨论】:

您能否添加一些有关在您的表上设置了哪些索引的信息?例如,在 tresults.StartTime 列上是否设置了索引? 我增加了一行。几乎所有在连接或 where 子句中的东西都被索引了。问题的根源在于连接(选择...)部分 【参考方案1】:

根据您的 SQL,我假设您仅列出基于 1 个供应商 (supplierID = 1) 的产品。

最佳做法是在 sql 开头执行 已知过滤器 以消除记录,然后使用内连接连接其他没有过滤器的表。

select p.pID, brandname, description, p.EAN, RetailPrice, LowestPrice, min(price), min(price)/lowestprice-1 as afwijking
from 
(select p.pID, p.BrandID p.EAN, Max(t.StartTime) AS maxstarttime
FROM tproducts p INNER JOIN tresults t on supplierID=1 and p.pID=t.pID
group by tresults.pID
) p 
inner join tresults res on (res.websiteID = 1 and p.pID = res.pID and res.starttime = p_max.maxstarttime)
inner join tsupplierproducts sp on (sp.pID = p.pID)
inner join tbrands b on (b.brandID = p.BrandID)
group by p.pID, brandname, description, p.EAN, RetailPrice, LowestPrice

从上面的代码中,我在加入结果之前从 tproducts 中删除了所有供应商ID!= 1。

如果上面的sql有帮助,请告诉我EXPLAIN函数的结果是什么

:-)

【讨论】:

谢谢。我消除了所有不是供应商ID = 1的产品。我以稍微不同的方式进行操作,因为供应商 ID 不在结果表中,也不在产品表中。速度稍微好一点,但不是很多。很可能是因为几乎所有产品都来自供应商 ID=1。 将这个添加到 where 子句有很大帮助:tresults.StartTime BETWEEN DATE_SUB(NOW(), INTERVAL 7 DAY) AND NOW()。我这样做是因为 maxdate 可能在过去 7 天内。但必须有更好的方法......我认为

以上是关于MySQL select in join 子句扫描太多行的主要内容,如果未能解决你的问题,请参考以下文章

强制 MySQL 从 WHERE IN 子句返回重复项而不使用 JOIN/UNION?

MySQL Select 语句,WHERE 'IN' 子句

优化 Sql Query 去掉 SELECT 子句并使用 JOIN

按mysql中select语句“in”子句中的值顺序排序

mysql优化总结

(转载)MySQL select 语句执行顺序