MySQL MAX()运行非常缓慢

时间:2019-09-02 08:44:58

标签: mysql performance max greatest-n-per-group

我正在运营一个网站,该网站允许用户抓取并分析其Instagram竞争对手/个人帐户,以监控其增长并查看进展情况以及他们是否符合增长目标。

对于网站的这一特定部分,我的一个MySQL查询的运行速度非常慢(每次4-6秒)。

我有两个表: -myaccounts(存储每个用户正在跟踪的所有帐户) -帐户(存储所有原始数据。每个帐户每2小时扫描一次,并在此处添加新记录)

这是运行速度非常慢的查询:

SELECT M.type, M.status, M.id as masterid, A.*
    FROM myaccounts as M
    INNER JOIN accounts as A on M.accountid = A.userid
    WHERE A.id = (
        SELECT MAX(id)
        FROM accounts 
        WHERE userid = M.accountid)
    AND M.userid = ?
    AND M.status = 'active'

使用EXPLAIN显示子查询实际上正在遍历表中的每一行(到目前为止大约180k)。

我使用MAX(id)的原因是我想在主页上显示帐户的最新数据,并为用户提供访问另一页上所有原始数据的选项。

有什么办法可以加快速度吗?在MAX()上使用某种INDEX?

谢谢! :)

标记

4 个答案:

答案 0 :(得分:0)

不幸的是,您将无法在字段的MAX()上创建索引,因为它是必须在运行时计算的值。唯一的方法是维护一个新字段,该字段存储最大值并在其上放置索引。但是,那么您将需要确保每次查询运行时都会更新该字段,这可能会更改其值。这样可以解决您的性能问题,但是通常不建议重复这样的数据,因为始终存在新字段与其余数据不同步的风险。

建议不要使用子查询,而应使用ORDER BY按accounts.id对全部结果进行排序,而不是这样做。然后,在查询末尾使用LIMIT 1来选择最前面的结果。更具体地说,查询看起来像这样:

SELECT M.type, M.status, M.id as masterid, A.*
FROM myaccounts as M
INNER JOIN accounts as A on M.accountid = A.userid
WHERE M.userid = ?
AND M.status = 'active'
ORDER BY A.id DESC
LIMIT 1

答案 1 :(得分:0)

您可以使用以下查询:

SELECT M.type, M.status, M.id as masterid, A.*
FROM myaccounts as M
INNER JOIN
(
 SELECT MAX(id), userid FROM accounts GROUP BY userid
)
AS A
on M.accountid = A.userid
WHERE
M.userid = ?
AND M.status = 'active'

答案 2 :(得分:0)

通过引入链接表lnk,您可以为每个用户ID提供max(id)s的“映射”。不会为每个记录生成(重新)该表。

SELECT M.type, M.status, M.id as masterid, A.*
    FROM myaccounts as M
    INNER JOIN
     ( SELECT userid uid, MAX(id) mid FROM  accounts GROUP BY userid ) lnk
    ON uid=accountid
    INNER JOIN accounts ON id=mid AND userid=accountid
    WHERE
    M.userid = ?
    M.status = 'active'

答案 3 :(得分:0)

那么,如果两个“用户”正在跟踪同一个“帐户”,则此查询将两次计算相同的信息?

由内向外翻转解决方案。首先为每个帐户找到“最后一个”条目,然后将其应用于您想要的位置。

myaccounts: INDEX(status, userid)   -- in either order
accounts:   INDEX(userid, id)       -- in this order