php - 优化此 SQL 查询的最佳方法是什么?

标签 php mysql sql doctrine

我试图在每页上获取 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);

这将是解释计划: enter image description here 我怎样才能优化这个查询以在更短的时间内获得结果?

最佳答案

执行计划显示仅使用了两个(主键)索引。这一点应该改进。除了主键索引之外,您还应该尝试使用额外的索引:

  • 职位(用户)
  • jobsmeta(parent_id)
  • jobs_locations_rel(parent_id)
  • usersmeta(parent_id,meta_key)

子查询可能也会减慢查询速度,子查询具有特殊的LIMIT 1。这意味着它检索的记录可能是多个记录中的随机一个。这要么意味着您的数据库设计不符合要求,要么意味着您不关心显示附件表的所有相关记录。使用不带 LIMITIN (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/

相关文章:

php - 注销后 Laravel 5 重定向 - 如何重定向回来?

php - 我怎样才能用 html 和 php 安排我的表格

mysql - sql右连接从右表返回多行

mysql - MySQL中的语法错误,但是在创建ROLE时语法正确

mysql LOAD DATA FILE 无法访问 unix shell 变量

php - 我必须在 exit() 之前 rollBack() 吗?

php - OpenCart 需要加载 CURL 扩展才能工作! php-5.3.13 和 WAMP

mysql - Postgres 中相当于 MySql 语句 GRANT USAGE ON *.* TO ‘%’ @’%’ REQUIRE SSL

mysql - 连接列,然后将它们分组在 MySQL 的特定范围内

sql - 了解 CUBE 和 ROLLUP 之间的差异