我正在尝试优化我的设计,但是很难正确看待事情。假设我有以下情况:
A.一个用户有 1,000 条状态更新。这些更新存储在单独的实体 Statuses 中。我想获取 uploadDate 在日期 X 之后的用户状态。所以我做了一个查询:
statuses = Statuses.query(Statuses.uploadDate > X).fetch()
B.一个用户有 1,000 条状态更新。每个 User 实体都有一个列表属性 list_of_status_keys
,它是用户状态的所有键的列表。我想获取日期 X 之后 uploadDate 的所有状态。因此,我可以使用 statuses = ndb.get_multi(list_of_status_keys)
轻松获取状态列表。然后我循环遍历每一个,检查日期:
for a_status in statuses:
if a_status.uploadDate > X:
myList.append(a_status)
我真的不知道应该优化哪个。查询看起来更有条理,但通过键获取更快。大家有什么见解吗?
更新
归根结底是这样的: 在对 GAE 的每个 http 请求中,我都会收到用户的所有通知和状态更新(就像 Facebook 一样)。使用 Appstats,它告诉我每个请求花费 490 微便士(其中 1 便士 = 1,000,000 微便士)。
获取通知和状态对于用户来说很重要,因此您可以预期他们会多次执行此操作。我很难确定这是否很多。我很害怕尝试以任何可能的方式最小化这个数字。我以前从未运行过服务,所以我不知道这是否应该花费多少钱。这是数学计算:
当没有结果返回时,每个请求花费 490 微便士(所以对于一个基本查询来说,它花费 490,但在某些情况下,当返回多个结果时,它可能花费 10,000 mp),所以对于 1 便士,我可以运行 2040请求,或者只要 1 美元,我就可以运行 204,000 个请求。
假设我有 50,000 个用户,每个用户每天检查通知 75 次(合理):
75 个请求 X 每个请求 490 mp X 50,000 个用户 = 每天 1,837,500,000 微便士 = 1837.5 便士 = 每天 18.37 美元。
(对吗?)
我以前从未运行过大规模服务,那么这些是常见的成本吗?或者这太高了?每次请求 490 微便士高吗?如果需要的话,我如何找到这个问题的答案?
最佳答案
设计 A 更优越。
在设计中,GAE 将使用日期来执行键控查询。这意味着,Appengine 将自动在按日期排序的状态表上为您创建索引。由于它有索引,因此它只会读取和获取您指定日期之后的记录。这将为您节省大量的读取次数。
在设计 B 中,您基本上必须自己完成索引工作。由于您需要获取每个状态,然后比较其日期,因此您必须做更多的工作,无论是在 CPU(即成本)方面还是在性能方面。
编辑
如果您的数据被如此频繁地访问,您可能还有其他设计选项。
首先,您可以考虑将 Status 对象合并到 StatusUpdatesPerDay 中。您每天都会创建一个实例,然后将状态更新附加到该对象。这会将数百次读取减少为几次读取。
其次,由于状态更新的访问会非常频繁,因此可以将状态缓存到memcache中。这将降低成本和延迟。
第三,即使你没有像上面那样优化,我相信ndb已经内置了缓存。我从未使用过此功能,但您的实际读取次数可能会低于您的计算结果。
第四个选项是避免一次显示所有状态更新。也许用户只想看到最后几个。然后,当(并且如果)用户请求时,您可以使用查询游标来获取剩余部分。
关于python - 我应该优化 Google App Engine 中的读取或 CPU 时间吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12484497/