我如何优化我的 MySQL 查询,因为它需要 45 秒来获取记录?

我如何优化我的 MySQL 查询,因为它需要 45 秒来获取记录?

SELECT `ringtunes`.*, count(case when ringtune_history.Action = 'Download' then ringtune_history.Action end) as Org_Downloads, count(case when ringtune_history.Action = 'View' then ringtune_history.Action end) as Org_Views, count(case when ringtune_history.Action = 'Play' then ringtune_history.Action end) as Total_Plays, count(case when ringtune_history.Action = 'Like' then ringtune_history.Action end) as Total_Likes, `categories`.`Name` as `Category_Name` FROM `ringtunes` LEFT JOIN `ringtune_history` ON `ringtune_history`.`Ringtune_Id` = `ringtunes`.`Id` LEFT JOIN `categories` ON `categories`.`Id` = `ringtunes`.`Category` WHERE `ringtunes`.`Deleted` = 0 AND `ringtunes`.`Status` = 1 AND `categories`.`Deleted` = 0 AND `categories`.`Status` = 1 GROUP BY `ringtunes`.`Id` ORDER BY `ringtunes`.`Id` DESC LIMIT 20;

除了限制返回结果行之外,LIMIT 20 不会为您做任何事情。它不会提高查询的内部性能。

值得一提的是 DB 查询优化器的第 0 条规则:他们做他们被编码要做的事情,而不是你想象的如果他们超级聪明和聪明的话他们可以做的事情。在这里,您可以想象 LIMIT 20 可以应用于连接的锚表,铃声,并在执行连接之前限制 *it*。但事实并非如此; MySQL 在查询主体被完全处理后应用 LIMIT。但是有一种方法可以使用 LIMIT 来提高查询性能,我将在下面展示……

GROUP BY 必须对所有连接的结果进行完全排序,而 LEFT JOIN 意味着您将得到一个工作集,其行数至少等于 ringtunes 表中的所有行。 WHERE 子句将过滤掉一些行,然后这个结果集将被排序和分组。

根据 ringtunes 表的大小,这是一个非常强大的查询,可以进行大量的连接和主动排序。计数,即使他们可能看起来很讨厌,也不应该是一个问题。

至于提高性能:

首先,分别获取您想要的 20 个 ID。 LIMIT 20 不会*这样做。

摆脱铃声。*。这可能是非法的 GROUP BY,因为 GROUP BY 中唯一允许的选择列表成员是明确的 GROUP 列(在本例中为 ringtunes.ID)或像 COUNT() 这样的聚合结果。你得到的结果将是随机的,不幸的是 MySQL 允许这种东西。

我假设至少有一个连接是 1:many,否则在 ringtunes 上分组。身份证没有任何意义。即便如此,请确保您加入索引列。

因此,一个可能的新查询可能类似于

SELECT ringtunes.ID, — get rid of ringtunes.* – fetch later if needed count(case when ringtune_history.Action = 'Download' then ringtune_history.Action end) as Org_Downloads, count(case when ringtune_history.Action = 'View' then ringtune_history.Action end) as Org_Views, count(case when ringtune_history.Action = 'Play' then ringtune_history.Action end) as Total_Plays, count(case when ringtune_history.Action = 'Like' then ringtune_history.Action end) as Total_Likes, `categories`.`Name` as `Category_Name` FROM (SELECT DISTINCT ringtunes.ID FROM ringtunes WHERE ringtunes.deleted = 0 and ringtunes.status = 1 ORDER BY ringtunes.ID DESC LIMIT 20) AS r_id JOIN ringtunes ON r_id.id = ringtunes.id LEFT JOIN `ringtune_history` ON `ringtune_history`.`Ringtune_Id` = `ringtunes`.`Id` LEFT JOIN `categories` ON `categories`.`Id` = `ringtunes`.`Category` WHERE `categories`.`Deleted` = 0 AND `categories`.`Status` = 1 — ringtunes WHERE filters are in the subquery above GROUP BY `ringtunes`.`Id` ORDER BY `ringtunes`.`Id` DESC;

这可能看起来更麻烦,因为它有初始子查询来获取您的 20 个有序 ID,但它应该更快,并且至少是一个合法的 GROUP BY。

如果铃声。 ID其实就是铃声的PK,你可以去掉上面的DISTINCT。

(0)
小多多的头像小多多创始人

相关推荐

发表回复

登录后才能评论