对在 Python App Engine 上使用数据存储进行分页感到困惑

Confused about using datastore for pagination on Python App Engine

我正在构建一个 Webapp2 应用程序,并试图找到分页的最佳解决方案。 我发现最流行的方法是使用 cursor。例如:

# My solution is to get all cursors in the very first time
# For example, there will be 2 cursors for 3 pages 
# page1|c1|page2|c2|page3

page_size = 20
all = model.MyModel.gql(...)
...
if cursor:
   # Use cursor to get items
   list = all.with_curosr(...)
else:
   # Get all cursors and memcaching all cursors
   ...

我也尝试了另一种解决方案,尽管我知道很多人会认为这是一个糟糕的解决方案:

# In this solution, I try to split query into many list
# page1(list1)|page2(list2)|page3(list3)

page_size = 20
all = list(model.MyModel.gql(...))
lists = [all[i:i+page_size] for i in range(0, len(all), page_size)]

# Client will send the page number to server side
list = []
if len(lists) > 0:
    list = lists[int(page_number)-1]

我的问题来了! 使用游标有什么好处?

两个方案都需要执行MyModel.gql(...)获取数据,第一个方案还是要执行with_cursor(...) 检索项目。 这让我很困惑。

如果您有更好的解决方案或者对我的解决方案有什么改进的建议,请与我分享!非常感谢!

使用游标与使用页面有很大的不同。使用游标时,获取下一个游标结果非常高效:最多O(1) 或O(log n)。

使用分页,整个数据存储查询结果需要扫描到您请求的页面:每个页面请求 O(n)。

因此,像使用游标迭代所有页面这样简单的事情最多将是 O(n log n),而使用页面将是 O(n^2)。它不仅需要更多时间,还需要更多数据存储读取,因为在内部 Google 仍会读取所有条目直到请求的页面,然后将它们过滤掉。

因此,如果您有很多请求并且更有可能启动另一个实例,那么它还会产生更多的数据存储读取成本,并且还会产生更多的实例小时数。

查看官方文档:https://cloud.google.com/appengine/docs/python/datastore/queries#Python_Offsets_versus_cursors