【发布时间】:2011-04-09 07:37:39
【问题描述】:
我正在尝试对 GAE 数据存储进行一些练习,以了解查询和计费机制。
我已阅读有关 GAE 的 Oreilly 书籍,并观看了有关数据存储的 Google 视频。我的问题是,最佳实践方法通常涉及对数据存储的读取多于写入。
我构建了一个超级简单的应用程序:
- 有两个网页 - 一个 选择链接,并选择一个视图 链接
- 每个用户都可以选择将 url 链接添加到他的“链接提要”中
- 用户可以随时选择任意数量的链接。
- 在另一个网页上,我想向用户显示他最近选择的 10 个链接。
- 每个用户都有自己的“链接提要”网页。
- 在我想保存并显示一些元数据的每个“链接”上 - 例如:url 链接本身;什么时候被选中;它已经在提要上出现了多少次;等
在这种情况下,由于用户可以选择他想要的任意数量的链接,所以我的应用程序写入数据存储区的次数远远多于读取次数(写入 - 当用户选择另一个链接时;读取 - 当用户打开网页以查看他的“链接提要”)
问题 1: 我可以想到(至少)两个选项来处理这个应用程序的数据:
选项 A: - 使用用户详细信息、注册等维护每个用户的实体 - 为每个用户维护另一个实体,保存他最近选择的 10 个链接,在他请求后将其呈现到用户的网页
选项 B: - 维护每个 url 链接的实体 - 这意味着所有用户的所有 url 都将存储为同一个对象 - 维护每个用户详细信息的实体(与选项 A 相同),但在 url 的大表中添加对用户 url 的引用
什么是更好的方法?
问题 2: 如果我想计算直到今天选择的 url 总数,或者用户选择的每日 url 数量,或者任何其他计算 - 我应该将它与我的 SDK 工具一起使用,还是应该在我上面描述的实体中插入计数器? (我想尽可能减少数据存储写入量)
编辑(回答@Elad 的评论): 假设我只想保存每个用户的最后 10 个网址。其余的我想摆脱(所以不要用不必要的数据填充我的数据库)。
编辑 2:添加代码后 所以我尝试了以下代码(尝试第一个 Elad 的方法):
这是我的课:
class UserChannel(db.Model):
currentUser = db.UserProperty()
userCount = db.IntegerProperty(default=0)
currentList = db.StringListProperty() #holds the last 20-30 urls
然后我将 url 和元数据序列化为 JSON 字符串,用户从第一页发布。 以下是 POST 的处理方式:
def post(self):
user = users.get_current_user()
if user:
logging messages for debugging
self.response.headers['Content-Type'] = 'text/html'
#self.response.out.write('<p>the user_id is: %s</p>' % user.user_id())
updating the new item that user adds
current_user = UserChannel.get_by_key_name(user.nickname())
dataJson = self.request.get('dataJson')
#self.response.out.write('<p>the dataJson is: %s</p>' % dataJson)
current_user.currentPlaylist.append(dataJson)
sizePlaylist= len(current_user.currentPlaylist)
self.response.out.write('<p>size of currentplaylist is: %s</p>' % sizePlaylist)
#whenever the list gets to 30 I cut it to be 20 long
if sizePlaylist > 30:
for i in range (0,9):
current_user.currentPlaylist.pop(i)
current_user.userCount +=1
current_user.put()
Updater().send_update(dataJson)
else:
self.response.headers['Content-Type'] = 'text/html'
self.response.out.write('user_not_logged_in')
Updater 是我使用 Channel-API 更新带有提要的网页的方法。
现在,一切正常,我可以看到每个用户都有一个包含 20-30 个链接的 ListProperty(当它达到 30 个时,我使用 pop() 将其减少到 20 个),但是!价格相当高... 像这里的每个 POST 需要 ~200 毫秒,121 cpu_ms,cpm_usd = 0.003588。考虑到我所做的只是将字符串保存到列表中,这非常昂贵...... 我认为问题可能是实体因大 ListProperty 而变大?
【问题讨论】:
-
从您的问题中不清楚您是要永久保存用户选择的所有 URL,还是只保存 20 个最近的 URL 并丢弃旧的。你能澄清一下吗?
-
你是对的。这是两种不同的情况。我用你评论的内容更新了我的问题。
-
太棒了 - 这让它更简单 - 请参阅下面的答案。顺便说一句,出于纯粹的好奇心,应用程序是什么?为什么我要保存一些 URL,但只能看到最后 10 个?
-
@Elad - 谢谢。 10 只是一个数字,它可以是任何数字,但我正在考虑一个动态提要,比如我的 facebook,只是我真的不需要超过 x 天的数据,因为它不相关。当然,将来我可能想永远保存用户的提要历史记录,但不是现在。
标签: python google-app-engine google-cloud-datastore