我正在运营一个网站,该网站允许用户抓取并分析其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?
谢谢! :)
标记
答案 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