2010-08-03 49 views
0

我一直在使用Google App Engine,並且遇到一些數據查詢緩慢的問題。我讀過設計一個App Engine數據存儲區與使用SQL數據庫不同的思維模式,我不確定我是否以最好的方式來做這件事。我有兩個問題,試圖得到正確的軌道上:GQL查詢優化和表架構

具體做法是:

我有一個Foo類型和UserFoo類型。每個UserFoo是對應的Foo的「實例」並保存特定於該實例的數據。我的Foo類型有一個fooCode屬性,它是一個唯一的標識符,我使用它們的fooCode屬性將每個UserFoo與各個Foo映射。然後,我對每個富的代碼運行,像這樣:

foos = Foo.all().filter('bar =', bar) 
for foo in foos: 
    userFoo = UserFoo.all().filter('userKey =', user).filter('fooCode =', foo.fooCode) 

注:我使用fooCode超過參考鍵,以便我們可以很容易地刪除並重新添加新Foo S和不必再重新映射所有對應UserFoo s。

一般來說:

什麼是設計GAE數據存儲表和最佳實踐使用它們典型的做法?

+0

Foo和UserFoo對象之間是否存在1對1的對應關係? – 2010-08-03 19:46:27

+0

請注意,您所展示的實際上並不是一個GQL查詢。 – 2010-08-03 19:48:50

+0

1 Foo許多用戶信息。另外,我最初調用的是GqlQuery,但改變了它們,因爲我讀得比較慢。 – 2010-08-03 19:52:54

回答

1

這是staircase of gets反模式。解決方案是ReferenceProperty pre-fetching

結果是你決定不使用ReferenceProperty。我建議你重新考慮這個選擇。

注:我使用fooCode在 參考鍵,以便我們可以很容易地 刪除並重新添加新的Foo而不是 有那麼重新映射所有 相應UserFoos。

請記住,實體鍵只是其路徑的編碼表示形式:實體及其任何祖先的種類和名稱或ID。如果您刪除並重新創建了Foo,則只有給予不同的名稱或ID時纔會有不同的密鑰。如果您可以通過某種方式向舊實體和新實體提供相同的fooCode,那麼您可以輕鬆使用fooCode作爲密鑰名稱,這將允許刪除然後重新添加Foo以保留其原始密鑰。

+0

閱讀這些鏈接很有意義。我現在正在修改我的數據存儲。感謝所有誰指出了這一點! – 2010-08-04 22:23:02

1

一般來說:

  • 去正規化儘可能。

  • 儘可能通過鑰匙 提及實體;它是最快的從數據存儲中獲取數據的方式。

具體而言,如果您使用ReferenceProperty建立關係而不是進入過濾器的代碼,那麼您的性能可能會大幅提升。我會猜測,查詢UserFoo的Foo比刪除和重新映射Foo更經常發生,是的?在這種情況下,務實和數據存儲明智的做法是使用引用屬性。另外,如果Foo-UserFoo關係可以非規範化爲單個實體,則完全不需要整個系列的查詢。

1

我建議以下變化:

  1. 使用的ReferenceProperty在UserFoo指其富,或者如果合適的話使子實體。我不明白你對重新映射現有實體的評論 - 這不應該是必要的。
  2. 爲每個UserFoo添加一個'bar'屬性的副本
  3. 對UserFoo.all()。filter('bar =',bar).order('userKey')執行一次查詢。結果將按欄過濾並按用戶分組,只需要一個查詢,而不是每個用戶一個。
  4. 通過在查詢上調用.fetch()來獲取結果,而不是遍歷它們。這樣更有效率。
  5. 如果需要,可使用ReferenceProperty prefetching檢索每個UserFoo的Foo對象。