MySQL怎样处理千万级数据分页 大表分页查询的优化方案

那天在地铁上,我看到旁边的人在使用一个电子商务应用程序。
每次下拉下载新产品都非常顺利。
我突然意识到,这背后肯定有数据库优化的成分。
再来说说千万级数据的分页。

例如:新闻APP首页推荐文章。
第一个请求可以是 SELECT id, title, excerpt FROM posts ORDER BYpublish_time DESC LIMIT 2 0,数据库将直接从最新的帖子开始扫描 2 0 个帖子。
下次刷新时,UI 将传递上一篇文章的 ID,并将其更改为 SELECT id, title, extract FROM Articles WHERE id < Last>这样数据库只检查该 ID 之前的记录,因此无需重新开始,速度要快得多。

但是如果搭建一个后台管理系统,管理员想要跳转到第5 0页查看用户命令,使用光标进行分页就会很麻烦。
此时,您可能必须使用子查询来查找第 5 0 页上的第一个订单 ID,然后从那里开始搜索。
例如:从订单中选择 id WHERE user_id = ? ORDER BY id LIMIT 4 9 , 1 .收到此ID后,执行SELECT FROM order WHERE id > ? LIMIT 2 0。
这比直接使用LIMIT 4 9 、2 0慢,但至少可以跳转页面。

另一个例子是报告系统,例如检查给定月份的销售额。
该数据每天更改一次,因此无需每次都检查数据库。
您可以一大早运行脚本,将结果保存到Redis,然后在检查报告时直接从缓存中获取。
如果数据变化非常频繁,您甚至可以创建实时计算表,例如使用物化视图。

最尴尬的就是查总数。
对于数千万数据,SELECT COUNT() FROM order 语句在运行时可能会损坏数据库。
此时,使用 SELECT COUNT(1 ) FROM (SELECT 1 FROM order LIMIT 1 000000) AS tmp 来估算大概的数量,否则 UI 会显示“Loading Total”,并且 UI 会打开一个异步任务来完成计算,然后通知 UI。
如果用户太不耐烦,就不要显示总数,而只是无限滚动,让用户计算他们看到的任何内容。

等等,还有一件事。
如果表中没有自增ID,例如按用户活动排序,则可以只使用WHERE create_at > 'last_time' AND id > 'last_id'。
这就要求排序字段是唯一的,否则数据库就得去重复,这样会更慢。

最后我想到分页的核心就是试图阻止数据库扫描全表。
指针分页最好,但应用最广泛的是LIMIT 1 00 OFFSET 2 00。
毕竟实现起来非常简单。
但与千万级数据,用过的人都知道背后的价格。

大数据量下的分页解决方法

去年夏天,我记得在图书馆的一个角落里寻找一本书。
这本书藏在书架的底部。
我必须踮起脚尖,伸出双臂。
结果我拿不到书,还被书架上积满的灰尘噎住了。
那一刻我突然想到,就像翻一本厚厚的书一样,翻阅海量的资料也是一页一页寻找信息的过程。
如果每次都像今天一样努力工作,那就是浪费时间。
在我看来,这就像生活中需要优化的任何方面一样,例如分页查询。
为了高效、简单,你需要找到最合适的方法。
等等,我记得有一次我试图使用移动应用程序查找特定地点,但由于分页问题而找不到最合适的路线。
这让我意识到分页不仅仅是一个技术问题,它还会影响用户体验。
那么有没有更好的方法来解决这个问题呢?