我有一个与 job_events 表左连接的 jobs 表。 job_events 表有一个关于 type 和 jobId 的索引。
当我按 jobs.id 订购查询时,结果会在 200 毫秒内显示。当我通过 job_events.created_at 订购时,需要 1.74 秒。
如何改进此查询,使其运行时间低于 1 秒。
这是 SQL 查询
SELECT *
FROM jobs
LEFT JOIN job_events ON job_events.jobId = jobs.id
AND job_events.id = (
SELECT MAX(id) FROM job_events
WHERE jobId = jobs.id
)
LEFT JOIN job_events created_by_events ON created_by_events.jobId = jobs.id
AND created_by_events.type = 'Created By'
AND created_by_events.id = (
SELECT MAX(id) FROM job_events
WHERE jobId = jobs.id AND type = created_by_events.type
)
LEFT JOIN job_events completed_job_events ON completed_job_events.jobId = jobs.id
AND completed_job_events.type IN ('Job Completed', 'Job Complete')
AND completed_job_events.id = (
SELECT MAX(id) FROM job_events
WHERE jobId = jobs.id AND type = completed_job_events.type
)
WHERE status IN (5, 6)
ORDER BY job_events.created_at
LIMIT 101;
Mysql详解:
当按
jobs.id
排序时,服务器只需要评估连接,直到有足够的行来满足限制子句。当按 job_events.created_at
排序时,它必须评估每个 jobs
行的连接。
您没有包含 DDL 或任何有关数据分布的信息,因此这有点盲目。
您可以将三个单独聚合的计算移至子查询并使用条件聚合:
SELECT *
FROM (
SELECT j.*,
MAX(je.id) AS max_id,
MAX(IF(je.type = 'Created By', je.id, NULL)) AS max_created_by_id,
MAX(IF(je.type IN ('Job Completed', 'Job Complete'), je.id, NULL)) AS max_completed_id
FROM jobs j
LEFT JOIN job_events je ON j.id = je.jobId
WHERE j.status IN (5, 6)
GROUP BY j.id
) AS temp
LEFT JOIN job_events je1 ON je1.id = temp.max_id
LEFT JOIN job_events je2 ON je2.id = temp.max_created_by_id
LEFT JOIN job_events je3 ON je3.id = temp.max_completed_id
ORDER BY je1.created_at ASC
LIMIT 101;