Mysql 使用 Order by Clause 性能非常慢
Mysql Very Slow Performance Using Order by Clause
我有一个 table 有数百万 entry.Below 是 table 结构。
CREATE TABLE `useractivity` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`userid` bigint(20) NOT NULL,
`likes` bigint(20) DEFAULT NULL,
`views` bigint(20) DEFAULT NULL,
`shares` bigint(20) DEFAULT NULL,
`totalcount` bigint(20) DEFAULT NULL,
`status` bigint(20) DEFAULT NULL,
`createdat` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `userid` (`userid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
下面是我的性能变慢的查询。
SELECT userid,
(sum(likes)+SUM(views)+SUM(shares)+SUM(totalcount)+SUM(`status`)) as total
from useractivity
GROUP BY userid
ORDER BY total DESC
limit 0, 20;
当我在没有 ORDER BY 的情况下执行上述查询时,它会给我快速的结果集但是当使用 ORDER BY 时,这个查询变慢了,尽管我使用了分页限制。
我可以做些什么来加快这个查询?
您不能按原样加速查询,MySQL 需要访问每一行并在排序之前计算总和,最后返回第一行。这必然需要时间。不过你可能会作弊。
最明显的方法是使用 userid 和总计创建摘要 table。当基础 table 发生变化时更新它或定期重新计算它,只要有意义。在那个 table 你可以索引总计,这使得查询变得微不足道。
另一种选择可能是找到顶级用户。大多数站点的用户都比其他站点更活跃。将前 1000 位顶级用户放在单独的 table 中,然后使用相同的 select,但仅限于顶级用户(即加入 table)。只需要访问顶级用户的用户活动行,这应该很快。如果 1000 个用户不够,也许 10000 个可以。
我有一个 table 有数百万 entry.Below 是 table 结构。
CREATE TABLE `useractivity` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`userid` bigint(20) NOT NULL,
`likes` bigint(20) DEFAULT NULL,
`views` bigint(20) DEFAULT NULL,
`shares` bigint(20) DEFAULT NULL,
`totalcount` bigint(20) DEFAULT NULL,
`status` bigint(20) DEFAULT NULL,
`createdat` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `userid` (`userid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
下面是我的性能变慢的查询。
SELECT userid,
(sum(likes)+SUM(views)+SUM(shares)+SUM(totalcount)+SUM(`status`)) as total
from useractivity
GROUP BY userid
ORDER BY total DESC
limit 0, 20;
当我在没有 ORDER BY 的情况下执行上述查询时,它会给我快速的结果集但是当使用 ORDER BY 时,这个查询变慢了,尽管我使用了分页限制。
我可以做些什么来加快这个查询?
您不能按原样加速查询,MySQL 需要访问每一行并在排序之前计算总和,最后返回第一行。这必然需要时间。不过你可能会作弊。
最明显的方法是使用 userid 和总计创建摘要 table。当基础 table 发生变化时更新它或定期重新计算它,只要有意义。在那个 table 你可以索引总计,这使得查询变得微不足道。
另一种选择可能是找到顶级用户。大多数站点的用户都比其他站点更活跃。将前 1000 位顶级用户放在单独的 table 中,然后使用相同的 select,但仅限于顶级用户(即加入 table)。只需要访问顶级用户的用户活动行,这应该很快。如果 1000 个用户不够,也许 10000 个可以。