- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
当您的内容排名可以快速变化时,分页很难,当这些排名因用户而异时,分页就更难了。 (让我们将无限滚动视为一种链接不可见的分页。)有两个难题:顶部的新添加内容和重新排列的内容。
让我们忘掉新添加的内容,接受您必须刷新第 1 页才能看到的事实。让我们也假装我们正在做纯 ORDER BY position
;如果您通过其他方式订购,则可能必须使用窗口函数。我们的页面每页有 4 行动物。他们开始:
+----+----------+-----------+
| id | position^| animal |
+----+----------+-----------+
| 1 | 1 | Alpacas |
| 2 | 2 | Bats |
| 3 | 3 | Cows |
| 4 | 4 | Dogs |
| 5 | 5 | Elephants |
| 6 | 6 | Foxes |
| 7 | 7 | Giraffes |
| 8 | 8 | Horses |
+----+----------+-----------+
在获取第 1 页之后和获取第 2 页之前,很多项目都在移动。数据库现在是:
+----+----------+-----------+
| id | position^| animal |
+----+----------+-----------+
| 4 | 1 | Dogs |
| 2 | 2 | Bats |
| 1 | 3 | Alpacas |
| 5 | 4 | Elephants |
| 6 | 5 | Foxes |
| 7 | 6 | Giraffes |
| 3 | 7 | Cows |
| 8 | 8 | Horses |
+----+----------+-----------+
常见的方法有以下三种:
偏移/限制方法
这是典型的幼稚方法;在 Rails 中,它是如何 will_paginate和 Kaminari工作。如果我想获取第 2 页,我会这样做
SELECT * FROM animals
ORDER BY animals.position
OFFSET ((:page_num - 1) * :page_size)
LIMIT :page_size;
获取第 5-8 行。我永远不会看到大象,但我会看到两次奶牛。
最后看到的 ID 方法
Reddit 采用不同的方法。客户端不是根据页面大小计算第一行,而是跟踪您看到的最后一个项目的 ID,就像书签一样。当您点击“下一步”时,他们会从该书签开始查找:
SELECT * FROM animals
WHERE position > (
SELECT position FROM animals
WHERE id = :last_seen_id
)
ORDER BY position
LIMIT :page_size;
在某些情况下,这比 page/offset 效果更好。但在我们的例子中,最后看到的帖子 Dogs 直接放大到 #1。所以客户端发送了 ?last_seen_id=4
,我的页面 2 是 Bats, Alpacas, Elephants and Foxes。我没有错过任何动物,但我看到了两次 bat 和羊驼。
服务器端状态
HackerNews(以及我们现在的网站)通过服务器端延续解决了这个问题;他们为您存储整个 结果集(或至少提前几页?),并且“更多”链接引用该延续。当我获取第 2 页时,我要求“我的原始查询的第 2 页”。它使用相同的偏移量/限制计算,但由于它是针对原始查询的,所以我根本不关心事情现在已经发生了变化。我看到大象、狐狸、长颈鹿和马。没有重复,没有遗漏元素。
缺点是我们必须在服务器上存储大量状态。在 HN 上,它存储在 RAM 中,实际上,这些延续通常在您按下“更多”按钮之前就过期了,迫使您一直返回到第 1 页以找到有效链接。在大多数应用程序中,您可以将其存储在 memcached 中,甚至可以存储在数据库本身中(使用您自己的表,或者在 Oracle 或 PostgreSQL 中,使用可保持游标)。根据您的应用程序,可能会影响性能;至少在 PostgreSQL 中,您必须找到一种方法来再次建立正确的数据库连接,这需要大量的粘性状态或一些巧妙的后端路由。
只有这三种可能的方法吗?如果没有,是否有计算机科学概念可以让我谷歌果汁来阅读这个?有没有办法在不存储整个结果集的情况下近似延续方法?从长远来看,存在复杂的事件流/时间点系统,其中“我获取第 1 页时的结果集”永远是可导出的。缺少那个...?
最佳答案
Oracle 很好地处理了这个问题。只要游标处于打开状态,您就可以根据需要多次提取,并且您的结果将始终反射(reflect)游标打开的时间点。它使用撤消日志中的数据来虚拟回滚游标打开后提交的更改。
只要所需的回滚数据仍然可用,它就会工作。最终日志被回收并且回滚数据不再可用,因此存在一些限制,具体取决于日志空间、系统事件等。
不幸的是(IMO),我不知道有任何其他数据库可以像这样工作。我使用过的其他数据库使用锁来确保读取一致性,如果您希望在非常短的时间内保持读取一致性,这就会出现问题。
关于database - 哪些分页方案可以处理快速变化的内容列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9602220/
如何更改循环中变量的名称?比如 number1 、 number2 、 number3 、 number4 ? var array = [2,4,6,8] func ap ( number1: Int
我想设置 View 的背景颜色并在一定延迟后将其更改为另一种颜色。这是我的尝试方式: print("setting color 1") self.view.backgroundColor = UICo
我在使用 express-session 时遇到问题。 session 数据不会在请求之间持续存在。 正如您在下面的代码中看到的那样,/join 路由设置了一些 session 属性,但是当 /sur
我试图从叶渲染器获得一个非常简单的结果,用于快速 Steam 的 for 循环。 我正在上传叶文件 HTML,因为它不接受此处格式正确的代码 - 下面的pizza.swift代码- import
你们中有人有什么好的链接可以与我分享吗?我正在寻找一个 FAST 程序员编辑器,它可以非常快速地打开包含超过 100, 000 行代码的文件?我目前正在使用记事本自动取款机,打开一个 29000 行长
我现在正在处理眼动追踪数据,因此拥有一个巨大的数据集(想想数百万行),因此希望有一种快速的方法来完成此任务。这是它的简化版本。 数据告诉您眼睛在每个时间点正在查看的位置以及我们正在查看的每个文件。 X
我是新手,想为计时器或其他设备选择提示音。 如何打开此列表,以选择其中一种声音? Alert sound list 最佳答案 您将无法在应用中使用系统声音。 但是,您可以包括自己的声音文件,并将其显示
我编写了以下代码来构建具有顺序字符串的数组。 它的工作方式与我预期的一样,但我希望它能更快地运行。有没有更有效的方法在PowerShell中产生我想要的结果? 我是PowerShell的新手,非常感谢
我有一个包含一些非唯一行的矩阵,例如: x 尝试 y <- rle(apply(x, 1, paste, collapse = " ")) # y$lengths is the vector con
我的函数“keyboardWillShown”有问题。所以我想要的是菜单打开时,菜单正好出现在键盘上方。它可以在Iphone 8 plus,8、7、6上完美运行。但是,当我在模拟器上运行Iphone
我正在尝试通过Swift 5中的HTTP get方法从API提取数据。它在启动时成功加载了数据,但是当我刷新页面时,它说“索引超出范围”,这是因为数据是不再会在我的日志中读取,因此索引中没有任何内容。
我想做什么: 从我的数据库中获取时间戳并将其转换为用户的时区。 我的代码: let tryItNow = "\(model.timestampName)" let format = D
给定字体名称和字体大小,如何查找字符串的宽度(CGFloat)? (目标是将UIView的宽度设置为足以容纳字符串的宽度。) 我有两个字符串:一个重复“1”,重复36次,另一个重复“M”,重复36次。
我正在尝试解析此JSON ["Items": ( { AccountBalance = 0; AlphabetType = 3; Description = "\U0631\U
我在UINavigationBar内放置了一个UILabel。 我想根据navigationBar的高度增加该标签的字体大小。当navigationBar很大时,我希望字体大小更大;当滚动并缩小nav
我想将用户输入限制为仅有效数字并使用以下内容: func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, rep
目前我有一个包含超过 100.000 张图像的数据库,它们大小不一或类似,但我想为我的公司制作以下内容: 我插入/上传一张图片,系统返回最有可能相同的图片。我不知道使用什么算法,但它需要快速。我可以预
在我的 swift 项目中,我有一个按钮,我想在标签上打印按下该按钮的时间。 如何解决这个问题? 最佳答案 添加到DHEERAJ的答案中,您只需在func press(sender: UIButton
我必须发表评论,尝试在解析中导入数组。然而,有一个问题。 当我尝试从 Parse 加载数组时,我的输出是 ("Blah","Blah","Blah")这是一个元组...而不是一个数组 TT... 如何
我的应用程序有一个名为 MyDevice 的类,我用它来与硬件通信。该硬件是可选的,实例变量也是可选的: var theDevice:MyDevice = nil 然后,在应用程序中,我必须初始化设备
我是一名优秀的程序员,十分优秀!