2

我正在尝试优化我的设计,但很难正确看待事物。假设我有以下情况:

A. 一个用户有 1,000 个状态更新。这些更新存储在单独的实体状态中。我想获取在日期 X 之后具有 uploadDate 的用户状态。所以我进行了查询:

statuses = Statuses.query(Statuses.uploadDate > X).fetch()

B. 一个用户有 1,000 个状态更新。每个用户实体都有一个列表属性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 requests X 490 mp per request X 50,000 users = 1,837,500,000 micropennies per day = 1837.5 pennies = 18.37 dollars per day.(是对的吗?)

我以前从未运行过大规模的服务,那么这些通常的成本是多少?还是这太高了?每个请求 490 小便士是否高?如果取决于情况,我将如何找到答案?

4

1 回答 1

2

设计 A 更胜一筹。

在设计中,GAE 将使用日期来执行键控查询。这意味着,Appengine 将自动为您在按日期排序的状态表上创建索引。由于它有一个索引,它只会读取和获取您指定日期之后的记录。这将为您节省大量读取。

在设计 B 中,您基本上必须自己完成索引工作。由于您需要获取每个状态然后比较其日期,您将不得不做更多的工作,无论是在 CPU(成本)方面还是在性能方面。

编辑

如果您的数据被如此频繁地访问,您可能还有其他设计选项。

首先,您可以考虑将 Status 对象组合到 StatusUpdatesPerDay 中。您每天创建一个实例,然后将状态更新附加到该对象。这会将数百次读取减少为几次读取。

其次,由于状态更新会被非常频繁地访问,因此可以将状态缓存在 memcache 中。这将降低成本和延迟。

第三,即使你没有像上面那样优化,我相信ndb已经内置了缓存。我从未使用过此功能,但您的实际读取计数可能低于您的计算。

第四个选项是避免一次显示所有状态更新。也许用户只想看到最后几个。然后,您可以使用查询游标在(如果)用户请求它们时获取余数。

于 2012-09-18T21:00:41.853 回答