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

时间:2015-07-06 11:43:06

标签: python google-app-engine pagination google-cloud-datastore

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

# 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(...)检索项目。 这让我很困惑。

如果您有更好的解决方案或任何改进我的解决方案的建议,请与我分享!非常感谢你!

1 个答案:

答案 0 :(得分:3)

使用游标与页面存在巨大差异。使用游标时,获取下一个游标结果非常有效:最多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