我知道这个问题已被问过100次了,这不是"我该怎么做",而是一个效率问题 - 一个我不太了解的话题。
从我的网络阅读中我已经找到了解决最近问题的一种方法,这种方法听起来非常有效 - LEFT JOIN a" max" table(按匹配条件分组)然后LEFT JOIN匹配分组条件的行。像这样:
Select employee.*, evaluation.* form employee
LEFT JOIN (select max(report_date) report_date, employee_id
from evaluation group by employee_id) most_recent_eval
on most_recent_eval.employee_id = employee.id
LEFT JOIN evaluation
on evaluation.employee_id = employee.id and evaluation.report_date = most_recent_eval.report_date
我不知道这有什么问题吗?这是2次表扫描(一次是查找最大值,一次是查找行)?是否必须为每位员工进行2次完整扫描?
我问的原因是我现在正在考虑加入3个表格,我需要最新的行(评估,安全许可和项目),似乎任何低效率都将大量增加。
有人可以给我一些建议吗?
答案 0 :(得分:0)
您建议的查询模式应该处于良好的状态。
一个可能的建议,如果您的evaluation
表格有自己的自动增量id
列,这将有所帮助。您可能能够使用此子查询找到每个员工的最新评估:
SELECT MAX(id) id
FROM evaluation
GROUP BY employee_id
然后您的加入可能如下所示:
FROM employee
LEFT JOIN (
SELECT MAX(id) id
FROM evaluation
GROUP BY employee_id
) most_recent_eval ON most_recent_eval.employee_id=employee.id
LEFT JOIN evaluation ON most_recent_eval.id = evaluation.id
如果id
表中的report_date
值和evaluation
值的顺序相同,则此方法有效。只有你知道你的申请中是否属于这种情况。但如果是,这是一个非常有用的优化。
除此之外,您可能需要向某些表添加一些复合索引以加快查询速度。首先让他们正常工作。阅读http://use-the-index-luke.com/。请记住,许多单列索引通常对MySQL查询性能有害,除非他们选择加速特定查询。
如果在(employee_id, report_date)
上创建复合索引,则此子查询
select max(report_date) report_date, employee_id
from evaluation
group by employee_id
可以满足于令人惊讶的效率loose index scan。同样,如果您使用InnoDB,则查询
SELECT MAX(id) id
FROM evaluation
GROUP BY employee_id
可以通过employee_id
上的单列索引上的松散索引扫描来满足。 (如果您正在使用MyISAM,则需要(employee_id, id)
上的复合索引,因为InnoDB将主键列隐式放入每个索引中。)