gpt4 book ai didi

mysql - where 子句中查询的查询性能问题

转载 作者:行者123 更新时间:2023-11-29 07:01:40 25 4
gpt4 key购买 nike

我有以下有点复杂的 sql 查询,它的性能很糟糕,“肯定”是由于 where 子句中的内部查询。在某些情况下,它需要一分钟多的时间。有人知道如何重写此查询以获得更好的性能吗?
查询:

SELECT DISTINCT t.id as taskId, t.name as taskName, 
t.startdate as taskStartDate, t.enddate as taskEndDate,
t.proj_id as taskProjectId
FROM PROJECT p, EMPL_PROJ ep, TASK t, TIMERECORD tr
WHERE
ep.empl_id = ? AND
ep.proj_id = p.id AND
ep.proj_id = t.proj_id AND
((p.startdate IS NULL AND p.enddate IS NULL) OR
(p.startdate IS NULL AND p.enddate >= ?) OR
(p.enddate IS NULL AND p.startdate <= ? + INTERVAL 6 DAY) OR
(p.startdate <= ? + INTERVAL 6 DAY AND p.enddate >= ?) ) AND
((t.startdate IS NULL AND t.enddate IS NULL) OR
(t.startdate IS NULL AND t.enddate >= ?) OR
(t.enddate IS NULL AND t.startdate <= ? + INTERVAL 6 DAY) OR
(t.startdate <= ? + INTERVAL 6 DAY AND t.enddate >= ?)) AND
(
(ep.empl_id = tr.empl_id AND
ep.proj_id = tr.proj_id AND
t.id = tr.task_id AND tr.day <= ? + INTERVAL 7 DAY AND
tr.day >= ? + INTERVAL -14 DAY
) OR
(
(SELECT count(*)
FROM TIMERECORD tr2
WHERE
tr2.empl_id=ep.empl_id AND
tr2.proj_id=p.id AND tr2.day <= ? + INTERVAL 7 DAY AND
tr2.day >= ? + INTERVAL -14 DAY) <= 0
)
)

我正在使用 mysql 服务器 5.1.40。

编辑 (2):有了评论和答案,我来到了这个查询,它在一秒钟内执行(差不多一分钟就不错了!)

SELECT DISTINCT t.id as taskId, t.name as taskName, 
t.startdate as taskStartDate, t.enddate as taskEndDate,
t.proj_id as taskProjectId
FROM (PROJECT p INNER JOIN EMPL_PROJ ep ON ep.proj_id = p.id)
INNER JOIN TASK t ON p.id=t.proj_id
INNER JOIN TIMERECORD tr ON tr.empl_id=ep.empl_id AND tr.proj_id=ep.proj_id
AND tr.task_id=t.id
WHERE
ep.empl_id = ? AND
((p.startdate IS NULL AND p.enddate IS NULL) OR
(p.startdate IS NULL AND p.enddate >= ?) OR
(p.enddate IS NULL AND p.startdate <= ? + INTERVAL 6 DAY) OR
(p.startdate <= ? + INTERVAL 6 DAY AND p.enddate >= ?) ) AND
((t.startdate IS NULL AND t.enddate IS NULL) OR
(t.startdate IS NULL AND t.enddate >= ?) OR
(t.enddate IS NULL AND t.startdate <= ? + INTERVAL 6 DAY) OR
(t.startdate <= ? + INTERVAL 6 DAY AND t.enddate >= ?)) AND
(
(
tr.day <= ? + INTERVAL 7 DAY AND
tr.day >= ? + INTERVAL -14 DAY
) OR
(
NOT EXISTS(SELECT *
FROM TIMERECORD tr2 INNER JOIN EMPL_PROJ ON tr2.empl_id=EMPL_PROJ.empl_id
INNER JOIN PROJECT ON PROJECT.id=tr2.proj_id
WHERE
tr2.day BETWEEN ? + INTERVAL -14 DAY AND ? + INTERVAL 7 DAY)
)
)
ORDER BY p.id, t.id

最大的贡献是建议使用 NOT EXISTS 方法(我标记为正确)的答案以及不要混合使用 explicitimplicit JOIN 的。

感谢大家!

最佳答案

当您似乎只需要一个 NOT EXISTS 时,您正在使用 COUNT(*)...

(
(SELECT count(*)
FROM TIMERECORD tr2
WHERE
tr2.empl_id=ep.empl_id AND
tr2.proj_id=p.id AND tr2.day <= ? + INTERVAL 7 DAY AND
tr2.day >= ? + INTERVAL -14 DAY) <= 0
)

替换为

(
NOT EXISTS(SELECT *
FROM TIMERECORD tr2
WHERE
tr2.empl_id=ep.empl_id AND
tr2.proj_id=p.id AND tr2.day <= ? + INTERVAL 7 DAY AND
tr2.day >= ? + INTERVAL -14 DAY)
)

现在,如果 TIMERECORD 确实存在,那部分 where 子句将短路为 FALSE(NOT TRUE),而不必计算每个 TIMERECORD。

关于mysql - where 子句中查询的查询性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9872045/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com