MySQL深分页调优实战

MySQL深分页调优实战,第1张

商品评论系统数据量为十亿量级,因此对评论数据库做分库分表,单表的评论数据在百万级别。

每个商品的所有评论都是放在一个库的一张表里,确保作为用户在分页查询一个商品的评论时,一般都是直接从一个库的一张表里执行分页查询语句即可。

热门商品销量多达上百万,商品评论可能多达几十万条。有些用户就喜欢看商品评论,他就喜欢不停对某个热门商品评论不断进行分页,一页一页翻,有时候还会用上分页跳转功能,就是直接输入自己要跳到第几页。

这就涉及针对一个商品几十万评论的深分页问题。

简化后的对评论表进行分页查询的SQL:

比如用户选择了查看某个商品的评论,因此必须限定 Product_id ,同时还选了只看好评,所以 is_good_commit 也要限定,

接着看第5001页评论,则limit的offset=(5001 - 1) * 20,20是每页的数量, 此时起始offset就是100000,所以limit后100000,20。

评论表最核心的索引 index_product_id ,所以正常肯定走这索引:

该过程有几十万次回表查询,还有十多万条数据的磁盘文件排序,所以要跑个1~2s。如何优化呢?

但本案例不是这样,因为

这俩条件不是一个联合索引,所以会出现大量回表,耗时严重。

因此对该案例,一般采取如下方式改造分页查询语句:

该SQL的执行计划就会彻底改变其执行方式。

通常先执行括号里的子查询,子查询反而会使用PRIMARY聚簇索引,按聚簇索引id值的倒序方向进行扫描,扫描过程中就把符合

的数据筛选出来。

比如这里筛选出10w条数据,并不需要把符合条件的数据都找到,因为limit 100000,20,理论上,只要有100000+20条符合条件的数据,且按id有序的,此时就能执行根据limit 100000,20提取到5001页的这20条数据。

接着你会看到执行计划里会针对这个子查询的结果集,一个临时表,进行全表扫描,拿到20条数据,再对20条数据遍历,每条数据都按id去聚簇索引查找一下完整数据。

所以本案例,反而是优化成这种方式来执行分页,更合适,他只有一个扫描【聚簇索引】筛选符合你分页所有数据的成本:

然后再做一页20条数据的20次回表查询即可。当时做了该分页优化后,发现分页语句一下子执行时间降低到了几百ms,达到优化目的。

SQL调优没有银d:

不同场景,要具体情况具体分析,到底慢在哪儿,再针对性优化。

假定你的图片表为tbpic,评论表tbcomment,图片表有自增id,评论表有自增id,图片id为picid,

第二个问题

select a.*,b.*  from tbpic a left join tbcomment b on a.id=b.picid

第一个问题

select a.*,b.*  from tbpic a left join (select *  from tbcomment where  id in ( select max(id) from tbcomment group by picid))  b on a.id=b.picid

用left join是为了考虑到图片可能有没被评论论过


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/7490594.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-06
下一篇 2023-04-06

发表评论

登录后才能评论

评论列表(0条)

保存