我试图在每页上获取 5 个作业结果(我使用带有 Doctrine 的 silex),但该页面加载大约需要 30-40 秒。
$sql = "
SELECT jobs.ID, jobs.date_added, jobs.user, jobs.title, jobsmeta.meta_value, jobs_locations_rel.county, jobs_locations_rel.city, usersmeta.meta_value, attachments.title
FROM jobs
JOIN jobsmeta
ON jobsmeta.parent_id = jobs.ID
JOIN jobs_locations_rel
ON jobs_locations_rel.parent_id = jobs.ID
JOIN usersmeta
ON usersmeta.parent_id = jobs.user
JOIN attachments
ON attachments.ID = (SELECT meta_value FROM usersmeta WHERE parent_id = jobs.ID AND meta_key = 'user_avatar' LIMIT 1)
ORDER BY jobs.date_added DESC LIMIT 5";
$data = $app['db']->fetchAll($sql);
最佳答案
执行计划显示仅使用了两个(主键)索引。这一点应该改进。除了主键索引之外,您还应该尝试使用额外的索引:
- 职位(用户)
- jobsmeta(parent_id)
- jobs_locations_rel(parent_id)
- usersmeta(parent_id,meta_key)
子查询可能也会减慢查询速度,子查询具有特殊的LIMIT 1
。这意味着它检索的记录可能是多个记录中的随机一个。这要么意味着您的数据库设计不符合要求,要么意味着您不关心显示附件表的所有相关记录。使用不带 LIMIT
的 IN (SELECT ...)
将确保您获得所有这些附件记录。
但比使用 IN
更好的方法是将其转换为额外的 JOIN
,如下所示:
SELECT jobs.ID, jobs.date_added, jobs.user, jobs.title,
jobsmeta.meta_value,
jobs_locations_rel.county, jobs_locations_rel.city,
m1.meta_value, attachments.title
FROM jobs
JOIN jobsmeta
ON jobsmeta.parent_id = jobs.ID
JOIN jobs_locations_rel
ON jobs_locations_rel.parent_id = jobs.ID
JOIN usersmeta m1
ON m1.parent_id = jobs.user
JOIN usersmeta m2
ON m2.parent_id = jobs.ID
AND m2.meta_key = 'user_avatar'
JOIN attachments
ON attachments.ID = m2.meta_value
ORDER BY jobs.date_added DESC
LIMIT 5
另一个奇怪的事情:usersmeta.parent_id
要么引用 jobs.ID
要么引用 jobs.user
值。这看起来像是您可能想要查看的数据库设计中的另一个缺陷。
如果“job.id”值的顺序与jobs.date_added
的顺序相同,那么您可以考虑执行ORDER BY jobs.id DESC
。如果没有,请考虑在 jobs(date_added)
上创建索引。
最后,您的 order by
不够具体,因为它允许对共享相同 jobs.id
的记录进行任意排序顺序。这与性能无关,但我预计它可能会使分页变得困难(取决于您如何实现它)。最好的情况是,您可以将 ORDER BY
子句中列出的列组合起来,共同唯一地标识结果中的记录。
关于php - 优化此 SQL 查询的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34454445/