2011-10-21 65 views
4

我有一個關於Google數據庫雲端數據存儲的設計問題。讓我用一個例子來解釋它:數據存儲設計 - 如何模擬高效連接

我有那種實體「文章」具有以下屬性:

  • 標題
  • 用戶id
  • ....
  • sumOfScore

相撲fScore應該是所有相關的 「分數」 的實體,它具有 性質類似的總和:

  • 條款ArticleID
  • 用戶id
  • 得分

僞SQL:
sumOfScore =從分數中選擇總和(分數),其中score.articleId = article.id

我看到兩種可能性來設計這個(使用谷歌的數據存儲API):

1)無財產sumOfScore的文章;但總是查詢:

這意味着:每次閱讀文章時,我需要爲計算sumOfScore的特定文章進行查詢。想象一下顯示給用戶的100篇文章的列表。這將需要額外的100個查詢到數據庫,只是爲了顯示每篇文章的分數。

儘管如此:當使用Relational-DB時,這將是我的首選方式。沒有冗餘和良好的標準化。 使用SQL,只需使用一個連接選擇即可捕獲所有數據。 但是它對雲數據存儲感覺不合適。

2)每當分數實體改變後計算sumOfScore:

這意味着:每當分數實體添加,刪除或更改,相關文章 更新sumOfScore財產。

優點:閱讀文章時不需要額外的查詢。 sumOfScore在實體本身上是多餘的。

缺點:每次更改分數時,都會有一個額外的查詢和一個額外的寫入(更新一個Article實體)。 sumOfScore可能與實際得分實體不匹配(例如,通過DB-Console更改值)

什麼是更有經驗的人認爲?這種情況下是否有一個常見的最佳做法? 什麼是在引擎蓋下做JPA或JDO實現?

非常感謝

莫斯

+0

您實際上並沒有使用Bigtable - 您使用的是App Engine數據存儲,它恰好建立在它上面,但提供了更多的功能。 –

回答

1

即使世界第三可能性不作出妥協。

你讓分數的孩子,並保持sumOfScore。爲了分類的目的,這個領域將派上用場。由於這兩個類來自同一個實體組,因此您可以創建一個得分,並在交易中更新文章。你甚至可以通過查詢所有的得分雙重檢查誰的父母是給定的

這種方法的問題是,你只能每秒更新一次實體5次。如果你認爲你有比這更多的活動(請記住,這只是一個單一的實體,而不是entier表的限制),你應該檢查出sharded counter tutorial或看到google io's video解釋這個..

編輯:

繼承人這個同一主題的大討論:How does Google Moderator avoid contention?

2

The first thing I recommend you look into the GAE article about sharding counters

這是來自GAE最佳實踐的文章,涉及如何處理計數器/金額。這可能有點棘手,因爲每次更新元素時​​都必須使用邏輯來隨機選擇一個分片計數器;當你檢索你的計數時,你實際上是獲取一組實體並對它們進行求和。我已經走了這條路,但不會在這裏提供代碼,因爲我還沒有對它進行測試。但是,如果您只是將示例分片代碼複製/粘貼到整個地方,那麼您的代碼可能會馬上變得sl so不安,因此如果決定採用這種方式,請使用抽象或類型計數器類來重用分片邏輯。

另一種方法是使用模糊計數。此方法使用memcache並以犧牲準確性爲代價提供更好的性能。

See the section here labeled "Transient and frequently updated data"

而且最後的選擇;只是使用SQL。 Its experimental and hot out of the oven (in relation to being used on GAE) but it might be worth looking into.