列表分页查询总数,查询耗时: 114s,数据量: 每张表平均150W,求大神赐教
发布于 6 年前 作者 wangbinlml 5097 次浏览 来自 问答

列表分页查询,求总数;

select count(*) AS num from tb_student stu inner join tb_student_parent stu_pa on stu.id = stu_pa.student_id AND stu.is_del=0 and stu_pa.is_del=0 inner join tb_parent pa on stu_pa.parent_id = pa.id and pa.is_del=0 where pa.phone = stu.phone;

数据量: 每张表平均150W, 查询耗时: 114s

where后面还有选项条件,先忽略; 求解优化;

21 回复

有建索引了吗

mysql话自己去折腾填坑。其他商业数据库或者pgsql,看查询计划

explain 看下有没有走索引 然后你说 where 条件先忽略,是不是可能是这方面的原因,比如可能需要复合索引之类的

提供一种思路,不是从数据库优化上的。不返回总页数,比如 一页 10条, 后端就查11条,前端收到如果有第11条时,可以加载第二页的按钮,如果少于11条,那正好没有下一页咯。

explain 一下 贴贴结果?

@rrbe 这是默认条件时候,还有一些不必填的搜索条件.

从 explain 的结果来看,主要耗时应该在第一次联表的时候,也就是你贴的 explain 结果的第一行,他返回了 69w 条记录,怎么能不慢…… 你说你一张表大概150w 数据,这个数据就占了一半了吧,时间复杂度上来看那几乎就等于全表扫描的平均时间了

原因的话我猜应该是 is_del 这个 key 了,如果数据量占一半以上,那在这个 key 上加索引实际应该是会降低查询效率的 你可以去掉这个 is_del 的索引再试试

楼主,上面sql的count出来的结果是多少?

来自酷炫的 CNodeMD

@rrbe 去掉is_del后rows是120w+,也很慢的

你都已经150W数据了还分页干什么?如果是数据分析的话没必要用sql哇,数据量一上来,你的sql优化的再好都是徒劳。

@wangbinlml 如果是光count都有150W的话,如果硬要优化,倒是可以走一个比较极端的方法,减少每个字段遍历的时间 这是一个和9楼完全相反的方法,不过你要确定is_del数字在127以内 is_del先改成tinyint count(*) 改为count(is_del) where的第一个条件改为 is_del=0 来命中is_del的索引 这样应该会快很多,但要质的飞跃,还是劝你放弃count 150W+次,因为这个相加mysql都是一个一个加的,索引做字典优化意义已经不大了

楼主这样的语句,从索引角度来优化,效果不大,因为这几乎是全表扫描了。但办法总是人想出来的,虽然mysql不像oralce有物理视图,但我们可以使用物理视图的概念。做法很简单,把楼主要的数据查出放到一个张表中,写一个存储过程每天更新一次,以后分页就是单表查询了。如果你对数据的时实要求很高,就在原来表中增加触发器,当数据改动时触发。但这样会造成性能上的损失,如何把握,楼主可以自已思考一下。

@zouzhenxing 也是一种解决办法,谢谢.

@zy445566 打算放弃count 150W+次,换种思路解决.

@xulayen 分页是可以的,尽量减少关联查询,单表Count(*),需要看其他信息可以点击详情查看.也是靠谱的

数据太多的话,一般都是加redis做缓存

看下mysql服务器 cpu 内存使用情况,如果cpu 内存使用率居高不下 那就需要升级配置了。 不能只从业务逻辑去分析。

先使用子查询作为虚拟表,再join可能效果要好一些~

回到顶部