Mysql 极慢的查询
下面是一个运行时间超过30秒的查询。基于我运行过的类似查询,我看不出阻塞在哪里。我唯一的想法是将job用户id加入到job_申请者的用户id中,但是他们需要被映射Mysql 极慢的查询,mysql,sql,query-performance,Mysql,Sql,Query Performance,下面是一个运行时间超过30秒的查询。基于我运行过的类似查询,我看不出阻塞在哪里。我唯一的想法是将job用户id加入到job_申请者的用户id中,但是他们需要被映射 SELECT DISTINCT u.user_id, u.first_name, u.last_name FROM users u LEFT OUTER JOIN employee_access ea ON ea.user_id = u.user_id LEFT OUTER JOIN confirmation c ON c.user_
SELECT DISTINCT u.user_id, u.first_name, u.last_name FROM users u
LEFT OUTER JOIN employee_access ea ON ea.user_id = u.user_id
LEFT OUTER JOIN confirmation c ON c.user_id = u.user_id
LEFT OUTER JOIN job_applicants a ON a.user_id = u.user_id
LEFT OUTER JOIN job j ON j.job_id = a.job_id
WHERE ea.access_id = 4 OR c.access_id = 4 OR (a.process_level = 0 AND j.access_id = 4)
ORDER BY u.last_name asc
使用
存在
:
select u.*
from users u
where exists (select 1
from employee_access ea
where ea.user_id = u.user_id and ea.access_id = 4
) or
exists (select 1
from confirmation c
where c.user_id = u.user_id and c.access_id = 4
) or
exists (select 1
from job_applicants a join
job j
on j.job_id = a.job_id
where a.user_id = u.user_id and
a.process_level = 0 AND j.access_id = 4
)
order by u.last_name;
这将防止所有笛卡尔积和最终删除重复项
我建议在以下方面建立索引:
用户(姓氏、用户id)
employee\u access(用户id,访问id)
确认(用户id、访问id)
求职者(用户id、流程级别、职位id)
作业(作业id、访问id)
存在
:
select u.*
from users u
where exists (select 1
from employee_access ea
where ea.user_id = u.user_id and ea.access_id = 4
) or
exists (select 1
from confirmation c
where c.user_id = u.user_id and c.access_id = 4
) or
exists (select 1
from job_applicants a join
job j
on j.job_id = a.job_id
where a.user_id = u.user_id and
a.process_level = 0 AND j.access_id = 4
)
order by u.last_name;
这将防止所有笛卡尔积和最终删除重复项
我建议在以下方面建立索引:
用户(姓氏、用户id)
employee\u access(用户id,访问id)
确认(用户id、访问id)
求职者(用户id、流程级别、职位id)
作业(作业id、访问id)
这应该行得通。这在概念上与Gordon的答案相似,但我对相关子查询有一种近乎病态的不信任
还有另一种方法。这样做的好处是首先收集
用户ID列表
,然后进入用户
,查看其他列:
SELECT u.user_id, u.first_name, u.last_name
FROM users u
JOIN (
( SELECT user_id FROM employee_access WHERE access_id = 4 )
UNION DISTINCT
( SELECT user_id FROM confirmation WHERE access_id = 4 )
UNION DISTINCT
( SELECT a.user_id
FROM job_applicants a
JOIN job j USING(job_id)
WHERE a.process_level = 0
AND j.access_id = 4 )
) AS x USING(user_id)
ORDER BY u.last_name ASC
索引:
employee_access: INDEX(access_id, user_id) -- (covering)
confirmation: INDEX(access_id, user_id) -- (covering)
job: INDEX(access_id, job_id) -- (covering)
job_applicants: INDEX(process_level, job_id, user_id) -- (covering)
users: PRIMARY KEY(user_id)
看看这是否会缩短剩下的8秒钟。还有另一种方法。这样做的好处是首先收集
用户ID列表
,然后进入用户
,查看其他列:
SELECT u.user_id, u.first_name, u.last_name
FROM users u
JOIN (
( SELECT user_id FROM employee_access WHERE access_id = 4 )
UNION DISTINCT
( SELECT user_id FROM confirmation WHERE access_id = 4 )
UNION DISTINCT
( SELECT a.user_id
FROM job_applicants a
JOIN job j USING(job_id)
WHERE a.process_level = 0
AND j.access_id = 4 )
) AS x USING(user_id)
ORDER BY u.last_name ASC
索引:
employee_access: INDEX(access_id, user_id) -- (covering)
confirmation: INDEX(access_id, user_id) -- (covering)
job: INDEX(access_id, job_id) -- (covering)
job_applicants: INDEX(process_level, job_id, user_id) -- (covering)
users: PRIMARY KEY(user_id)
看看这是否会缩短剩下的8秒钟。您的桌子有多大?它们是如何编制索引的?你也可以发布查询的解释吗。(只需在选择并运行查询前加上“EXPLAIN”)所有这些表中的主键是
user\u id
?如果没有,是否索引?您的表有多大?它们是如何编制索引的?你也可以发布查询的解释吗。(只需在选择并运行查询前加上“EXPLAIN”)所有这些表中的主键是user\u id
?如果没有,它是索引的吗?在看到您的答案后,我现在明白了为什么原始查询使用外部联接——它只需要处理其他一个表中的ID匹配。在不更新索引的情况下,这个更新的查询缩短了20秒(8秒对28秒)。非常感谢。一旦更新的索引到位,将对速度留下评论。对于求职者
我会使用索引(用户id、流程级别、流程id)
,因为在使用工作id
加入下一个表之前,您首先要按流程级别
进行筛选。很好。在看到您的答案后,我现在明白了为什么原始查询使用外部联接——它只需要处理其他一个表中的ID匹配。在不更新索引的情况下,这个更新的查询缩短了20秒(8秒对28秒)。非常感谢。一旦更新的索引到位,将对速度留下评论。对于求职者
我会使用索引(用户id、流程级别、流程id)
,因为在使用工作id
加入下一个表之前,您首先要按流程级别
进行筛选。接得好,确实是这样。这很快!的确如此。这很快!