引言
最近在做一个社区的项目,在这个过程中遇到了一个性能方面的问题,通过不断调研得出了一个解决方案,所以写个文章分享记录一下。
问题
在社区项目中,在查询帖子时,每当分页查询的数量越大时,比如在我要查询第200多页时的帖子时,发现点击对应的按钮的运行速度会比之前卡很多。
解决方案
考虑从sql查询语句上进行优化。
//优化前的sql
SELECT id, user_id, title, content, TYPE, STATUS, create_time, comment_count, score
FROM discuss_post
WHERE STATUS !=2
ORDER BY TYPE DESC
LIMIT 1001,5
此时相当于是全表扫描,因此效率较低。
//优化后的sql
SELECT a.id,a.user_id, a.title, a.content, a.type, a.status, a.create_time, a.comment_count, a.score
FROM discuss_post AS a
INNER JOIN
(
SELECT id FROM discuss_post
WHERE STATUS !=2
ORDER BY TYPE DESC
LIMIT 1001,5
)AS b ON a.id = b.id
优化后的sql就是走主键索引了,能够提高效率。
总结
未优化的sql相当于是一次性的查询,如果是一次性全部查询出来,这里mysql的做法是需要一个回表查询,就是因为mysql这些数据都是存储在叶子结点上,如果直接一次性查询的话,它是根据这个id回到主表上再进行一次查询,也就是说要遍历两次,并不是说把b+树一次性遍历取出所有的数据。
而优化后的sql相当于是二次查询,但是是走索引的,所以效率高。具体来说,采用的方法是只查它的id。这样它就不要回表查询了,因为它在id的这个b+树上它就只存了id,然后我查出来这些数据相当于就是锁定出了数据范围,然后这些id就相当于是作为了表的外键,然后再使用这个外键和主表进行联表查询,就是查这个主表里的id等于之前查出的id,进行二次查询。这样的话相当于它是走了底层的索引的,扫描了尽可能少的页面,效率就会快很多。