之前已经提出过这个问题,但我不满意,需要进一步阐述。
这些是基本前提:
我不确定我是否理解它,但这是我如何阅读给定的解释。
我的问题是:
如果cursorMark想知道要跳过哪些文件,那么这不是一个搜索?它基本上是通过运行一系列文档并提出问题来进行搜索,这是我正在寻找的还是我需要跳过这个?"
仍然与第一个问题有关,这个"文件序列"如何计算?是不是存储在内存中?或者是cursorMark创建存储在磁盘上的临时文件?
如果它不记得整个结果范围,它如何计算下一个cursorMark?
我所能看到的是,没有逃脱。
您可以存储有关搜索结果的某些状态,也可以搜索每个网页请求。
相关参考资料:
cursorMark is stateless and how it solves deep paging
How much time does the cursorMark is available on solr server
答案 0 :(得分:1)
cursorMark不会影响搜索 - 搜索仍然按原样执行。 cursorMark不是一个索引或与实际搜索的执行方式相关,但它是一种允许通过大型数据集进行有效分页的策略。这也意味着你的第二个问题没有实际意义,因为它没有改变实际搜索的执行方式。
当您考虑Solr服务器的集群的情况时,例如在SolrCloud模式下运行时,cursorMark解决深度分页的原因变得明显。
我们假设您有四台服务器A
,B
,C
和D
,并希望从第400行开始检索10个文档(我们假设一个服务器==一个较大集合的一个分片,以使这更容易)。
在常规情况下,您必须从检索开始(按排序顺序,因为每个节点将根据您的查询对其结果集进行排序 - 这与任何常规查询都不同,因为它将需要在本地进行排序),然后合并:
您现在必须浏览1640个文档才能找到实际结果集的内容,因为它可能就是您正在寻找的10个文档,所有文件都存在于服务器上C
。或者可能是服务器B
上的350,而服务器D
上的其余部分。如果没有从每个服务器实际检索410个文档,就不可能说。结果集将被合并和排序,直到跳过400个文档并找到10个文档。
现在说你想要从第1行开始的10个文件 - 你必须从每个服务器检索1 000 010个文件,并通过4 000 040个文件的结果集进行合并和排序。随着服务器和文档数量的增加,您可以看到这种情况变得越来越昂贵,只是为了将起点增加10个文档。
相反,让我们假设你知道全局排序顺序(意味着返回的最后一个文档的词法排序值)是什么。 第一个查询,没有一个cursorMark,将与常规分页相同 - 从每个服务器获取前10个文档(因为我们从一开始就开始)结果集(而不是第一个例子中的位置400),我们每个服务器只需要10个。)
我们处理这40个文档(一个非常易于管理的大小),对它们进行排序并检索10个第一个文档,然后我们包含最后一个文档的全局排序键(cursorMark)。然后客户端包括这个"全局排序键"在请求中,我们可以说"好的,我们对在本文档前面排序的任何条目不感兴趣,因为我们已经显示了那些"。然后,下一个查询将执行:
cursorMark
cursorMark
cursorMark
cursorMark
现在我们仍只是从每个服务器返回10个文档,即使我们的cursorMark
在分页深度上有一百万行。我们以前必须检索的地方,排序(好吧 - 我们可以假设它们从结果集中返回,所以我们必须通过结果集找到第一百万个条目,然后从集合中选择下一个,在检索它们并处理4 000 040个文档后,我们现在只需要检索40个文档并在本地对它们进行排序,以便返回实际的10个文档。
为了进一步解释cursorMark
如何工作,让我们假设这种方法只适用于具有整数值的唯一列(因为这样可以更容易地显示cursorMark在内部表示的内容,以及为什么the uniqueKey has to be present in the sort)(如果uniqueKey不存在,如果cursorMark最终出现在具有多个相同的排序字段值的文档上,我们可能会随机结束丢失的文档):
A B C D
1 2 3 4
8 7 6 5
9 10 11 12
13 14 15 16
17 20 21 22
18 23 25 27
19 24 26 28
我们从cursorMark 7开始请求4个值(rows = 4)。每个服务器然后可以查看其结果集(在内部排序,因为所有结果集都是),并从中检索4个值排序顺序为7之后的值:(<表示这是cursorMark之后的第一个值,+表示此文档包含在从节点返回的结果集中)
A B C D
1 2 3 4
8 < 7 6 5
9 + 10 < 11 < 12 <
13 + 14 + 15 + 16 +
17 + 20 + 21 + 22 +
18 23 + 25 + 27 +
19 24 26 28
然后我们遍历返回的每个结果集,直到我们从顶部选择了四个文档:
8 (from A)
9 (from A)
10 (from B)
11 (from C)
我们包含最后一个文档的cursorMark:11。然后使用11作为cursorMark进行下一个请求,这意味着每个服务器可以从11之后的条目开始返回4个文档:
A B C D
1 2 3 4
8 7 6 5
9 10 11 12 <
13 < 14 < 15 < 16 +
17 + 20 + 21 + 22 +
18 + 23 + 25 + 27 +
19 + 24 + 26 + 28
然后我们再次执行合并,按排序顺序选择前4个条目,并包含下一个cursorMark。
..这回答了第三个问题:它不需要知道全局状态,只需要从巨大的数据集中返回的下一个结果。