千万条数据,Stack Overflow是如何实现快速分页的

转载自 千万条数据,Stack Overflow是如何实现快速分页的

Stack Overflow 在分页机制中使用页码代替偏移量,页码指向基于 LIMIT 和 OFFSET 的查询。假设要对 1000 万条记录进行分页,跳到最后一页会非常慢,但 Stack Overflow 还是想办法实现了快速分页。

那么 Stack Overflow 是如何实现快速分页的呢?缓存热门查询并在应用程序代码中实现分页?还是使用了什么数据库黑魔法?

实际上,整个分页过程是非常复杂的。但我会尝试以一种简单的方式告诉你其中的原理,而不是写一个包含很多页内容的帖子。

假设  

说到分页,基本上是围绕 pageNumber * pageSize 而展开的。也就是说,要在已排好序的 n 条记录中获得当前的集合,可以将 pageNumber 乘以 pageSize,然后再加上 pageSize,就可以返回当前结果。在我们的例子中,它实际上是(pageNumber - 1)* pageSize,因为页面 1 的索引是 0。

在排序问题上,我们不需要完全排序整个集合,而是对 pageNumber * pageSize 条数据进行排序,这样就可以得到当前页面排好序的数据,而剩余部分可能只进行部分排序。与其排序整个集合并返回前 n 个结果,不如只对集合的前 n 个结果进行排序并返回这些结果。这样做很合理。

另外需要注意的是,最耗资源的查询总是那些中间页。获取最后 n 个页面与获得前 n 个页面一样容易:只需进行反向排序即可。比如,在按照日期降序排序时获取 pageNumber 1 与在按照日期升序排列时获取 pageNumber n-1 一样,都很容易。很多排序引擎(数据库、搜索引擎等)都使用了这种优化方式,我们也一样。

为了方便讨论,我们假定问题就是帖子,反之亦然,因为我会在文中交替使用这两个名词。

第 1 步:Tag Engine

我们有一个自己开发的.NET 应用程序,叫作 Tag Engine,它包含了帖子 ID 和元数据。我们把它看作是一个倒排索引,可以通过数据(如创建日期、标签、分数等)查找帖子 ID。

Tag Engine 主要负责基于某些限制条件做一些集合操作,比如它对一系列帖子 ID 集合进行交集、联合等操作,以便得到最终结果,并且还可以基于元数据在内存中进行排序。

我们使用 pageNumber 和 pageSize 以及一些限制条件(比如 Site ID,因为 Tag Engine 负责处理所有站点的查询)向 Tag Engine 发起查询。它在内存中进行集合操作(如联合和交集),然后对结果进行排序,返回相关的帖子 ID 子集。

Tag Engine 还会缓存查询结果(是集合,而不仅仅是请求的页面),并且可以根据由查询(页码、页面大小、排序方式等)哈希生成的缓存键从特定的缓存结果集中快速选择一个页面。这样极大提升了查询性能。

第 2 步:数据库

Tag Engine 不包含实际的数据,仅包含 ID 和元数据。因此,我们用帖子 ID 的结果集来查询数据库。查询看起来像这样:

Select p.*, pm.ViewCount, u.Id, u.ProfileImageUrl, ...From Posts pJoin PostMetadata pm On p.Id = pm.PostIdLeft Join Users u On p.LastActivityUserId = u.IdWhere p.Id In @Ids";

这里的 @Ids 是指 Tag Engine 中包含的 ID 列表。这个查询将返回实际的数据,但事情还没完。

步骤 3:半冗余的内存排序

如上所述,Tag Engine 可能会返回缓存的数据。然而,就其性质而言,缓存数据不能保证准确性(因为它们有可能是过去状态的快照)。相比之下,数据库始终具有最新的数据。

为了解决这个问题,我们在内存中再次对结果页面进行排序。

不过有一点比较让人头疼:最后一次内存排序基本上就是调用 List.Sort,并传进去一个排序函数。排序函数因用户查看不同的页面而有所不同:对于“Newest”页面,它会比较创建日期,而对于“Votes”,它会比较分数等。

如果我们没有做最后一步,帖子在页面上显示时可能会出现乱序,因为它们在 Tag Engine 中的排序反映的是过去的状态,而不是数据库的当前状态。

最后,我们把问题列表显示出来!

原文链接:https://meta.stackoverflow.com/questions/322164/how-does-stack-overflow-do-pagination


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330144.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu系统下安装docker并部署Springboot+mysql+redis

目录安装DockerDocker常用命令构建mysql容器构建Redis容器构建Springboot应用镜像及容器(1)springboot使用maven将程序打成jar包,接着编写Dokerfile文件,[Dockerfile详细介绍](http://www.dockerinfo.net/dockerfile%e4%bb%8b%e7%…

redis连接池

【README】 本文旨在po出 redis连接池的测试用例 <dependencies><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.5.1</version></dependency></dependencies> 【1】 代…

qmc0转换mp3工具_GoldenRecords for Mac(唱片录音转换软件)

想要将你最喜欢的唱片音乐转换成为方便易于携带的数字音频么&#xff1f;GoldenRecords Mac版是一款Macos上的唱片录音转换软件&#xff0c;用户可以将自己收藏的旧唱片快速转换成为自己喜欢的数字音频音乐&#xff0c;随时随地想听就听&#xff01;GoldenRecords mac版&#x…

java提高篇之抽象类与接口

转载自 java提高篇之抽象类与接口 接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法。 抽象类与接口是java语言中对抽象概念进行定义的两种机制&#xff0c;正是由于他们的存在才赋予java强大的面向对象的能力。他们两者之间对抽象概念的支持有很大的相似&…

Java中synchronized同步块的执行流程

必要知识 Java 对象的数据结构 在 HotSpot 虚拟机中&#xff0c;Java 对象在内存中存储的布局可以分为 3 块区域&#xff1a;对象头&#xff08;Header&#xff09;、实例数据&#xff08;Instance Data&#xff09;和对齐填充&#xff08;Padding&#xff09;对象头中的 Mar…

深入理解Java的接口和抽象类

转载自 深入理解Java的接口和抽象类 对于面向对象编程来说&#xff0c;抽象是它的一大特征之一。在Java中&#xff0c;可以通过两种形式来体现OOP的抽象&#xff1a;接口和抽象类。这两者有太多相似的地方&#xff0c;又有太多不同的地方。很多人在初学的时候会以为它们可以随意…

转: 记录centos7 安装erlang22.3和rabbitMQ

转&#xff1a; https://blog.csdn.net/weixin_44436611/article/details/109492936 记录centos7 安装erlang22.3和rabbitMQ 记录centos7 安装erlang22.3和rabbitMQTOC 官网地址&#xff1a;https://www.rabbitmq.com/install-rpm.html#install-erlang 部分rpm包&#xff1a;…

hashmap应用场景_工作中常用到的Java集合有哪些?应用场景是什么?

秋招Java面试大纲&#xff1a;Java并发spring数据库RedisJVMNetty等疫情期间“闭关修炼”&#xff0c;吃透这本Java核心知识&#xff0c;跳槽面试不心慌Spring全家桶笔记&#xff1a;SpringSpring BootSpring CloudSpring MVC前言Java集合是我认为在Java基础中最最重要的知识点…

Zookeeper入门总结

什么是Zookeeper 官方定义&#xff1a; zookeeper是一个分布式服务框架&#xff0c;是Apache Hadoop 的一个子项目&#xff0c;它主要是用来解决分布式应用中经常遇到的一些数据管理问题&#xff0c;如&#xff1a;统一命名服务、状态同步服务、集群管理、分布式应用配置项的管…

rabbitmq启动失败-报Failed to load advanced configuration file解决方法

【README】 1、本文基于 centos8 搭建 rabbitmq&#xff1b; 版本信息如下&#xff1a; rabbitmq rabbitmq-server-3.8.12-1.el8.noarch.rpm erlang erlang 23.2.5 (erts-11.1.8) 上述两者版本一定要强对应&#xff0c;否则mq启动失败&#xff0c;参见官网 https://rabb…

Java抽象类与接口的区别

转载自 Java抽象类与接口的区别 抽象类 抽象类是用来捕捉子类的通用特性的 。它不能被实例化&#xff0c;只能被用作子类的超类。抽象类是被用来创建继承层级里子类的模板。以JDK中的GenericServlet为例&#xff1a; public abstract class GenericServlet implements Servlet…

gateway坑点:gateway有Controller时会直接处理对应的路径并返回

前言 使用gateway过程中&#xff0c;因为在gateway中加入了一个标注RestController的类&#xff0c;导致请求直接由gateway中的RestController的类处理并返回。花费了几小时才发现问题原因&#xff0c;特此记录 问题 以gateway作为网关转发请求得到的响应&#xff0c;所有字…

电脑任务栏跑到右边去了_电脑没有声音怎么解决 电脑没有声音解决方法【详解】...

电脑没有声音怎么办? 这个话题在我耳边已经听到过了无数次了&#xff0c;处理故障也是由以前的摸索解决到现在可以快速的找到原因。但对于新手朋友来说可能不知道从哪里入手&#xff0c;对于电脑没有声音怎么办&#xff0c;也给不出一个对策&#xff0c;今天围绕这个问题&…

rabbitmq-java生产者消费者

【README】 本文使用java 连接rabbitmq&#xff0c;模拟生产者&#xff0c;消费者场景 【1】项目搭建 1&#xff09;maven项目&#xff0c;依赖 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance…

Java 8新特性——default方法(defender方法)介绍

转载自 Java 8新特性——default方法&#xff08;defender方法&#xff09;介绍 我们都知道在Java语言的接口中只能定义方法名&#xff0c;而不能包含方法的具体实现代码。接口中定义的方法必须在接口的非抽象子类中实现。下面就是关于接口的一个例子&#xff1a; 1 2 3 4 5 6 …

对于高并发的理解及实践方案

目录01 如何理解高并发&#xff1f;02 高并发系统设计的目标是什么&#xff1f;2.1标题宏观目标高并发绝不意味着只追求高性能&#xff0c;这是很多人片面的理解。2.2 微观目标2.2.1 性能指标2.2.2 可用性指标2.2.3 可扩展性指标03 高并发的实践方案有哪些&#xff1f;3.1 通用…

ubuntu ifconfig_Ubuntu 设置固定 IP 最简单的方法!

因为鼠标共享软件需要使用网络连接&#xff0c;台式机的 IP 总是变化导致笔记本每次重启都要重新配置 IP&#xff0c;所以我给 ubuntu 设置了固定 IP&#xff0c;方法很简单&#xff0c;直接再系统设置里面配置就可以了。1. 查看默认网络配置打开系统「Setting」&#xff0c;打…

rabbitmq-发布订阅模式

【README】 本文po出 mq的发布订阅模式&#xff0c;及代码示例&#xff1b; 【1】intro 1&#xff09; 角色&#xff1a; 有4个角色&#xff0c; 包括 生产者&#xff0c;消费者&#xff0c; 交换机 exchange&#xff08;X&#xff09;&#xff0c; 队列&#xff1b; 2&#…

深入Java类型信息:RTTI和反射

转载自 「深入Java」类型信息&#xff1a;RTTI和反射 1.RTTI Run-Time Type Infomation 运行时类型信息 为什么需要RTTI&#xff1f; 越是优秀的面向对象设计&#xff0c;越是强调高内聚低耦合&#xff0c;正如依赖倒转原则所说&#xff1a;“无论是高层模块还是低层模块&#…

设计费收费标准2002修订_@设计师,2019景观园林设计收费标准,注意查收!

From&#xff1a;景观邦(ID&#xff1a;LA_bang)一、设计费量的定制&#xff1a;设计费在10万以上的(包括10万)省外工程方能承接。其工作内容有:景观概念规划设计、方案设计、初步设计、施工图设计、效果图绘制及多媒体制作等。二、设计费的取费标准&#xff1a;居住区、道路、…