【问题标题】:MYSQL Query Optimization with subqueries and joinsMYSQL 查询优化与子查询和连接
【发布时间】:2020-05-10 17:50:34
【问题描述】:

您好,我有 800 万行数据,需要优化 Mysql 查询以从该数据中获取一行。我正在使用以下查询,但它的服务器响应时间太长,导致页面加载速度出现问题

SELECT q.id
     , q.title
     , q.question
     , q.price
     , q.created
     , q.userid
     , q.duedate
     , q.tags
     , s.id subjectid
     , sc.id subcategoryid
     , s.title subject
     , sc.title subcategory
     , q.statusid
     , (SELECT  COUNT(id) FROM tbl_answers a WHERE a.questionid = q.id AND a.statusid = 1 AND a.deleted = 'N') q_num_answers
     , u.username
     , u.image
     , u.gender
     , (SELECT  COUNT(id) FROM tbl_answers a WHERE a.userid = q.userid AND a.statusid = 1 AND a.deleted = 'N') num_answers
     , (SELECT  COUNT(id) FROM tbl_questions WHERE userid = q.userid AND statusid = 1 AND deleted = 'N') AS num_questions
     , 0 amt_earned
     , 0 amt_spent
     , 0 num_sold
     , (SELECT  COUNT(ur.id) FROM tbl_users_ratings ur WHERE ur.userid = q.userid AND ur.deleted = 'N') u_num_ratings
     , (SELECT  COALESCE(SUM(ur.rating), 0) FROM tbl_users_ratings ur WHERE ur.userid = q.userid AND ur.deleted = 'N') u_score
  FROM tbl_questions q
  JOIN tbl_subjects s 
    ON q.subject = s.id
  JOIN tbl_subjects sc 
    ON q.subcategory = sc.id
  LEFT 
  JOIN tbl_users u 
    ON u.id = q.userid
 WHERE q.deleted = '$show_deleted' 
   AND q.id = ? 
 LIMIT 1

【问题讨论】:

  • 请注意,没有 ORDER BY 的 LIMIT 是毫无意义的。如果是我,我会看到 Why should I provide an MCRE for what seems to me to be a very simple SQL query? 并重新开始。
  • 另外,您对 SQL 注入持开放态度,但我希望您已经意识到这一点。
  • 哦,请注意(以及所有相关表的 SHOW CREATE TABLE 语句)有关查询优化的问题始终需要给定查询的 EXPLAIN。
  • @Strawberry Limit without order by 并非毫无意义——它返回那么多行。如果这不是他们想要的,那就不是他们想要的。
  • @Strawberry 和 philipxy 感谢您的帮助。我知道 SQL 注入和其他事情,我只需要帮助来优化我的 sql 查询,因此它需要更少的执行时间。

标签: mysql join subquery database-partitioning mysql-slow-query-log


【解决方案1】:

这些索引可能有帮助。 (我假设id 是每个表的PRIMARY KEY。)

ur:  (deleted, userid, rating)
a:  (deleted, statusid, userid)
a:  (deleted, statusid, questionid)

请提供EXPLAIN SELECT ...

不要使用COUNT(id),除非您需要检查id 不是NULL。通常的写法是COUNT(*)

在一个地方,您正在检查为deleted 提供的值。在另一种情况下,您对其进行硬编码。也许错了?

AND  ur.deleted = 'N'

如果 qPRIMARY KEYid,那么这将导致 1 行或没有行。我错过了什么?

    WHERE  q.deleted = '$show_deleted'
      AND  q.id = ?

(可能还有更多提示。请更改我建议的内容并按照其他人的建议进行。然后再看一下。)

【讨论】:

    猜你喜欢
    • 2015-05-19
    • 1970-01-01
    • 1970-01-01
    • 2010-11-06
    • 2012-11-26
    • 2023-01-03
    • 2015-07-22
    • 2020-02-14
    • 2017-04-04
    相关资源
    最近更新 更多