极慢的查询
Extremely slow query
下面是一个需要 30 多秒才能到达 运行 的查询。基于我有 运行ning 的类似查询,我看不出问题在哪里。我唯一的想法是将作业用户 ID 加入 job_applicants 用户 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_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
使用exists
:
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;
这将阻止所有笛卡尔积和最终去除重复项。
我会推荐以下索引:
users(last_name, user_id)
employee_access(user_id, access_id)
confirmation(user_id, access_id)
job_applicants(user_id, process_level, job_id)
job(job_id, access_id)
这应该有效。它在概念上与 Gordon 的回答相似 但我对相关子查询有一种病态的不信任。
SELECT DISTINCT u.user_id, u.first_name, u.last_name
FROM users u
WHERE u.user_id IN (SELECT user_id FROM employee_access WHERE access_id = 4)
OR u.user_id IN (SELECT user_id FROM confirmation WHERE access_id = 4)
OR u.user_id IN (
SELECT a.user_id
FROM job_applicants a
INNER JOIN job j ON j.job_id = a.job_id
WHERE a.process_level = 0 AND j.access_id = 4
)
ORDER BY u.last_name asc
另一种方法。这具有 首先 收集 user_ids
列表的优势, 然后 进入 users
其他列:
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 秒的大部分时间。
下面是一个需要 30 多秒才能到达 运行 的查询。基于我有 运行ning 的类似查询,我看不出问题在哪里。我唯一的想法是将作业用户 ID 加入 job_applicants 用户 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_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
使用exists
:
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;
这将阻止所有笛卡尔积和最终去除重复项。
我会推荐以下索引:
users(last_name, user_id)
employee_access(user_id, access_id)
confirmation(user_id, access_id)
job_applicants(user_id, process_level, job_id)
job(job_id, access_id)
这应该有效。它在概念上与 Gordon 的回答相似 但我对相关子查询有一种病态的不信任。
SELECT DISTINCT u.user_id, u.first_name, u.last_name
FROM users u
WHERE u.user_id IN (SELECT user_id FROM employee_access WHERE access_id = 4)
OR u.user_id IN (SELECT user_id FROM confirmation WHERE access_id = 4)
OR u.user_id IN (
SELECT a.user_id
FROM job_applicants a
INNER JOIN job j ON j.job_id = a.job_id
WHERE a.process_level = 0 AND j.access_id = 4
)
ORDER BY u.last_name asc
另一种方法。这具有 首先 收集 user_ids
列表的优势, 然后 进入 users
其他列:
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 秒的大部分时间。