如何重写这个嵌套的 SQL 查询以使其更快?

How to rewrite this nested SQL query to make it faster?

本次查询return16000条记录,耗时约3-4分钟!我在查询末尾添加了 LIMIT 10,但没有任何区别。

更新:这里是解释输出:

$sql = "
        SELECT *,GROUP_CONCAT(`firstName`,' ',`lastName` SEPARATOR '<br/>') AS `users` 
        from (SELECT `frk_item`.`itemId`,`frk_quotes`.`quoteId`,`frk_item`.`title`,`quoteno`,`gmp`,`value`,`values`,`status`,`dates`,`firstName`,`lastName`,`name`,`frk_quoteuser`.`userid` 
        FROM `frk_item` INNER JOIN `frk_quotes` ON `frk_item`.`itemId` = `frk_quotes`.`itemId` 
        LEFT JOIN `frk_project` ON `frk_project`.`projectId` = `frk_item`.`projectId` 
        LEFT JOIN `frk_quoteuser` ON `frk_quoteuser`.`quoteId`=`frk_quotes`.`quoteId` 
        LEFT JOIN `frk_member` ON `frk_member`.`memberId` = `frk_quoteuser`.`userId` 
        WHERE `frk_quotes`.`varis`='original' AND `frk_quotes`.`status`!='0'" . $filter . "  
        order by `frk_item`.`quoteno` DESC) as `poop` 
        GROUP BY `quoteId` 
        ORDER BY `quoteno` DESC";

更新: Rick James 关于添加索引的建议解决了这个问题。现在加载记录需要 2-3 秒

  • 从 MyISAM 切换到 InnoDB。
  • 什么是 $filter
  • status有多少个不同的值?如果只有两个,则改为AND status = 1.
  • frk_quotes: 添加INDEX(varis, status, quoteId, itemId)
  • frk_quoteuser 需要 INDEX(quoteId, userId)
  • 这似乎没用:LEFT JOIN frk_member ON frk_member.memberId = frk_quoteuser.userId。不需要就不要加。
  • 去掉内层ORDER BY;它没有任何用处。
  • 请对每一列进行限定。
  • INT(4) 上的 (4) 没有任何意义。请参阅 TINYINT 及其兄弟姐妹。
  • 由于GROUP BYORDER BY不同,所以可能还有第二种排序。
  • LIMIT 10 没用,因为没有办法设计一个索引来处理 WHERE and GROUP BY ORDER BY。这就是所有的工作都完成了,然后交付了 10 行。这节省了网络流量,但之前没有任何工作。

尽你所能解决这些问题,然后在需要时回来接受更多批评。