[AppEngine] 實戰 Datastore API (3)

Datastore 為了資料的延展性(scalability),資料被擺放的位置可能不如你預期(比方說最近兩個 record 會放在附近等),如果不了解一點 Datastore 的設計哲學,可能會在抓資料時拖低整個系統的效率。

Datastore 提出了 entity group 的概念,簡單地說,被放在同一個 entity group 的資料會比較容易擺在附近,也就是你在抓取同一個 group 的資料時會快上許多,而且在 Datastore 裡,一次 transaction 只能對同一 group 的資料運作,好處是做交易時不用鎖住整個 datastore 而提升同時寫入的效率,而壞處當然就是程式不那麼好寫囉 😛

什麼時候會用到 entity group 呢?舉個例子來說,你今天也許在做一個多部落格的 CMS 系統,每個 blog 有自己的文章,但與其它的 blog 文章則較無關係,如此你便可以把同一個 blog 的文章都設成同一個 entity group,這樣在讀取某個 blog 時,它便能夠很快地讀入所有文章,而且在寫入或交易時,並不會影響到其它 blog。

那..那..那要怎麼設 entity group 呢?首先我們得了解 Datastore 裡,資料之間其實是可以設定 parent 的,所謂的 entity group,就是「你跟你的 parent 及 ancestor (祖先)」視為同一個 entity group。ya, 沒錯,就是這麼簡單,所以上述那個 blog 的例子要怎麼實作呢?

所以你可能有一個 Blog 及 Post 的 model,一個是用來儲存 blog,另一個則是 blog 文章,其實你只要在新增 Post 的資料時,多設定 parent 指到它所屬的 blog 就好,你的 code 可能會這樣寫:


blog = Blog.get_by_key_name('blog1')
....
new_post = Post(parent=blog,
key_name='blog1_'+str(max_id), ....)
new_post.put()

這樣設定之後,你在取得某個 post 若還只是用 GQL 來抓的話,那就沒有完全發揮 entity group 的效果,所以大概要這樣寫:


post = Post.get_by_key_name('blog1_'+str(id),
parent=Key.from_path('Blog', 'blog1'))

也就是要指定它的 parent 來取得會快很多,這裡就是利用 db.Key 的 from_path 來根據 key_name 來找到當初設定的 parent,所以在 Datastore 中,為資料加上 key_name 是很重要的,如果不太清楚 key_name 是什麼的話,那就複習一下第二集吧 😛

所以同理可證,當你要做文章留言的 model 時,也可以把 comment 的 parent 指向 Post,如此在抓文章的同時,再抓 comment 也不會花太多時間了。

  • wens

    感覺就是可以把ptt丟上去

    一個版一個entity group XDD

  • 樓上正妹要衝了嗎?