列表分页查询,求总数;
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后面还有选项条件,先忽略; 求解优化;
有建索引了吗
mysql话自己去折腾填坑。其他商业数据库或者pgsql,看查询计划
@WillZWL 有索引
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+,也很慢的
@zy445566 150W左右
你都已经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可能效果要好一些~