mySQL 查询随机执行需要很长时间
mySQL query Randomly takes a long time to execute
我是查询优化的新手,所以我已经阅读了很多文章并观看了 YouTube 等内容,但我仍然无法弄明白。
问题是我想为 API 执行此查询:
SELECT req_id,follow_requests.insta_id as id,caption,follow_requests.male,
users.name,users.profile_pic
FROM follow_requests
INNER JOIN users ON follow_requests.insta_id = users.insta_id
WHERE (remaining_follow>0 && req_id<='574989')
AND NOT EXISTS
(
SELECT *
FROM follows
WHERE follows.req_id=follow_requests.req_id
AND follows.follower_insta_id='3134816134'
)
ORDER BY req_id DESC
LIMIT 20
所以我记录了我的数据库,摘要显示这个正在占用我 +42% 的资源
此查询的某些实例看起来像 300 秒,平均为 20 秒!(他们卡在发送数据状态)
所以我试着把它改得更好(不是我真的知道我在做什么 :)
我把它改成了这个
SELECT fr.req_id, fr.insta_id as id, fr.caption, fr.male, u.name,
u.profile_pic, fr.date, fr.remaining_follow
FROM follow_requests AS fr
INNER JOIN users AS u ON fr.insta_id=u.insta_id
WHERE fr.remaining_follow>0
AND fr.insta_id!=3134816134
AND NOT EXISTS
(
SELECT *
FROM follows as f
WHERE f.req_id=fr.req_id
AND f.follower_insta_id='3134816134'
)
ORDER BY fr.date DESC
LIMIT 20
奇怪的是,前几次运行还可以!像从 0.1 秒到 0.7 秒
在试运行中
但是在我稍微伸展一下然后回来完成它之后,这也停留了 +200,300 秒但是这次在排序状态
我用 explain 检查了查询,发现它没有使用日期索引!
如果我只从查询中删除 'order by' 部分,它就会变得非常快 ~0.2s
有什么想法吗?
顺便说一句,几乎所有的列都被索引了,并且跟随 table 有 2M 行其他有 +100k
抱歉,如果我不能很好地解释它或者我错过了给你一些重要的信息,我是新手 ;)
如果您能以新手可以理解的方式解释它,同时又不会遗漏重要细节,我将不胜感激:)
提前致谢
=-=-=-=-=-=-= 更新1 =-=-=-=-=-=-=
感谢您的帮助,我现在找到了这个查询,虽然省时但
我不得不稍微改变一下整个事情,但它可能仍然有问题
SELECT follow_requests.req_id, follow_requests.insta_id as id,
caption, follow_requests.male, users.name,users.profile_pic
FROM follow_requests
INNER JOIN users ON follow_requests.insta_id = users.insta_id
LEFT OUTER JOIN follows ON follows.req_id = follow_requests.req_id
AND follows.follower_insta_id = '3134816134'
WHERE follow_requests.remaining_follow >0
AND follow_requests.insta_id != 3134816134
AND (follows.follower_insta_id != 3134816134 || follows.follower_insta_id is null)
ORDER BY follow_requests.date DESC
LIMIT 20
嗯,首先我要说的是我没有写原始查询(第一个)而且我自己也不理解所有的内容:/但是主程序员现在是遥不可及的,我必须代替他否则整个项目将失败
关于这个问题,每个人都可以为 insta_id 提交多个请求,但应该只 return 其中一个
主要代码和@Kickstart 代码(这是原始代码的优化版本,平均响应时间约为 10 秒)是否正确(出于某种原因我不明白
但是我的代码 returns 相同 insta_id 的多个实例(具有不同的 req_id)
还有人能告诉我为什么第一个查询表现如此糟糕吗?
我得到了 2 个解决方案
第一名:
而不是使用 "select *" 使用 "select id"
SELECT fr.req_id, fr.insta_id as id, fr.caption, fr.male, u.name, u.profile_pic, fr.date, fr.remaining_follow
FROM follow_requests AS fr INNER JOIN users AS u
ON fr.insta_id=u.insta_id
WHERE fr.remaining_follow>0 AND fr.insta_id!=3134816134
AND NOT EXISTS (SELECT f.id FROM follows as f WHERE f.req_id=fr.req_id AND f.follower_insta_id='3134816134')
ORDER BY fr.date DESC LIMIT 20
2ND:
你可以的
SELECT fr.req_id,
fr.insta_id AS id,
fr.caption,
fr.male,
u.name,
u.profile_pic,
fr.date,
fr.remaining_follow
FROM follow_requests AS fr
INNER JOIN users AS u
ON fr.insta_id = u.insta_id
INNER JOIN follows AS f
ON f.req_id = fr.req_id
AND f.follower_insta_id != '3134816134'
WHERE fr.remaining_follow > 0
AND fr.insta_id != 3134816134
ORDER BY fr.date DESC
LIMIT 20
确实需要查看 table 声明和查询的 EXPLAIN。
然而,可能值得尝试以下 table 的 LEFT OUTER JOIN,并检查是否匹配(通过检查必须在 table 上填充的列是否为 NULL) .
但是,您是否有包含 req_id 和 follower_insta_id 字段的以下 table 的索引?不是 2 个单独的索引,而是一个涵盖两个领域的索引。
SELECT req_id,
follow_requests.insta_id as id,
caption,
follow_requests.male,
users.name,users.profile_pic
FROM follow_requests
INNER JOIN users ON follow_requests.insta_id = users.insta_id
LEFT OUTER JOIN follows ON follows.req_id = follow_requests.req_id AND follows.follower_insta_id = '3134816134'
WHERE follows.req_id IS NULL
AND remaining_follow > 0
AND req_id <= '574989'
ORDER BY req_id DESC
LIMIT 20
我是查询优化的新手,所以我已经阅读了很多文章并观看了 YouTube 等内容,但我仍然无法弄明白。
问题是我想为 API 执行此查询:
SELECT req_id,follow_requests.insta_id as id,caption,follow_requests.male,
users.name,users.profile_pic
FROM follow_requests
INNER JOIN users ON follow_requests.insta_id = users.insta_id
WHERE (remaining_follow>0 && req_id<='574989')
AND NOT EXISTS
(
SELECT *
FROM follows
WHERE follows.req_id=follow_requests.req_id
AND follows.follower_insta_id='3134816134'
)
ORDER BY req_id DESC
LIMIT 20
所以我记录了我的数据库,摘要显示这个正在占用我 +42% 的资源 此查询的某些实例看起来像 300 秒,平均为 20 秒!(他们卡在发送数据状态) 所以我试着把它改得更好(不是我真的知道我在做什么 :) 我把它改成了这个
SELECT fr.req_id, fr.insta_id as id, fr.caption, fr.male, u.name,
u.profile_pic, fr.date, fr.remaining_follow
FROM follow_requests AS fr
INNER JOIN users AS u ON fr.insta_id=u.insta_id
WHERE fr.remaining_follow>0
AND fr.insta_id!=3134816134
AND NOT EXISTS
(
SELECT *
FROM follows as f
WHERE f.req_id=fr.req_id
AND f.follower_insta_id='3134816134'
)
ORDER BY fr.date DESC
LIMIT 20
奇怪的是,前几次运行还可以!像从 0.1 秒到 0.7 秒 在试运行中 但是在我稍微伸展一下然后回来完成它之后,这也停留了 +200,300 秒但是这次在排序状态 我用 explain 检查了查询,发现它没有使用日期索引! 如果我只从查询中删除 'order by' 部分,它就会变得非常快 ~0.2s
有什么想法吗?
顺便说一句,几乎所有的列都被索引了,并且跟随 table 有 2M 行其他有 +100k
抱歉,如果我不能很好地解释它或者我错过了给你一些重要的信息,我是新手 ;)
如果您能以新手可以理解的方式解释它,同时又不会遗漏重要细节,我将不胜感激:)
提前致谢
=-=-=-=-=-=-= 更新1 =-=-=-=-=-=-=
感谢您的帮助,我现在找到了这个查询,虽然省时但 我不得不稍微改变一下整个事情,但它可能仍然有问题
SELECT follow_requests.req_id, follow_requests.insta_id as id,
caption, follow_requests.male, users.name,users.profile_pic
FROM follow_requests
INNER JOIN users ON follow_requests.insta_id = users.insta_id
LEFT OUTER JOIN follows ON follows.req_id = follow_requests.req_id
AND follows.follower_insta_id = '3134816134'
WHERE follow_requests.remaining_follow >0
AND follow_requests.insta_id != 3134816134
AND (follows.follower_insta_id != 3134816134 || follows.follower_insta_id is null)
ORDER BY follow_requests.date DESC
LIMIT 20
嗯,首先我要说的是我没有写原始查询(第一个)而且我自己也不理解所有的内容:/但是主程序员现在是遥不可及的,我必须代替他否则整个项目将失败
关于这个问题,每个人都可以为 insta_id 提交多个请求,但应该只 return 其中一个 主要代码和@Kickstart 代码(这是原始代码的优化版本,平均响应时间约为 10 秒)是否正确(出于某种原因我不明白 但是我的代码 returns 相同 insta_id 的多个实例(具有不同的 req_id)
还有人能告诉我为什么第一个查询表现如此糟糕吗?
我得到了 2 个解决方案
第一名:
而不是使用 "select *" 使用 "select id"
SELECT fr.req_id, fr.insta_id as id, fr.caption, fr.male, u.name, u.profile_pic, fr.date, fr.remaining_follow
FROM follow_requests AS fr INNER JOIN users AS u
ON fr.insta_id=u.insta_id
WHERE fr.remaining_follow>0 AND fr.insta_id!=3134816134
AND NOT EXISTS (SELECT f.id FROM follows as f WHERE f.req_id=fr.req_id AND f.follower_insta_id='3134816134')
ORDER BY fr.date DESC LIMIT 20
2ND:
你可以的
SELECT fr.req_id,
fr.insta_id AS id,
fr.caption,
fr.male,
u.name,
u.profile_pic,
fr.date,
fr.remaining_follow
FROM follow_requests AS fr
INNER JOIN users AS u
ON fr.insta_id = u.insta_id
INNER JOIN follows AS f
ON f.req_id = fr.req_id
AND f.follower_insta_id != '3134816134'
WHERE fr.remaining_follow > 0
AND fr.insta_id != 3134816134
ORDER BY fr.date DESC
LIMIT 20
确实需要查看 table 声明和查询的 EXPLAIN。
然而,可能值得尝试以下 table 的 LEFT OUTER JOIN,并检查是否匹配(通过检查必须在 table 上填充的列是否为 NULL) .
但是,您是否有包含 req_id 和 follower_insta_id 字段的以下 table 的索引?不是 2 个单独的索引,而是一个涵盖两个领域的索引。
SELECT req_id,
follow_requests.insta_id as id,
caption,
follow_requests.male,
users.name,users.profile_pic
FROM follow_requests
INNER JOIN users ON follow_requests.insta_id = users.insta_id
LEFT OUTER JOIN follows ON follows.req_id = follow_requests.req_id AND follows.follower_insta_id = '3134816134'
WHERE follows.req_id IS NULL
AND remaining_follow > 0
AND req_id <= '574989'
ORDER BY req_id DESC
LIMIT 20