如何重写这个嵌套的 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 BY
和ORDER BY
不同,所以可能还有第二种排序。
LIMIT 10
没用,因为没有办法设计一个索引来处理 WHERE
and GROUP BY
和ORDER BY
。这就是所有的工作都完成了,然后交付了 10 行。这节省了网络流量,但之前没有任何工作。
尽你所能解决这些问题,然后在需要时回来接受更多批评。
本次查询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
ONfrk_member
.memberId
=frk_quoteuser
.userId
。不需要就不要加。 - 去掉内层
ORDER BY
;它没有任何用处。 - 请对每一列进行限定。
INT(4)
上的(4)
没有任何意义。请参阅TINYINT
及其兄弟姐妹。- 由于
GROUP BY
和ORDER BY
不同,所以可能还有第二种排序。 LIMIT 10
没用,因为没有办法设计一个索引来处理WHERE
andGROUP BY
和ORDER BY
。这就是所有的工作都完成了,然后交付了 10 行。这节省了网络流量,但之前没有任何工作。
尽你所能解决这些问题,然后在需要时回来接受更多批评。