我有一個應用程序,其中有我的用戶將瀏覽的項目列表。我已經通過索引字段處理分頁(我還需要它用於其他的事情,所以我想爲什麼不)。Appengine查詢偏移 - 不適用於尋呼 - 編輯與Memcache?
我的問題是,我想實現一個「goto」功能;用戶可以直接跳到一個項目,而不是通過使用提供的導航按鈕(下一個和上一個)對它們進行分頁。例如,他們可以在「goto」框中輸入1000,並顯示第1000個項目。第n項和它的索引之間有一個斷開 - 索引保證按順序排列,但不能保證是順序的,所以我不能只按索引進行篩選。我想過使用fetch
的offset
參數,但我記得當我第一次使用appengine開始編程時,由於性能問題我被告知不要使用它。
offset
會是最好的方式去這裏,或者有更好的方法嗎?另外,與它相關的成本只是需要更長時間才能得到結果,還是會計入我的數據存儲讀取/小操作?
編輯:我並不是說這是一個壞的方式,但爲了避開那些會告訴我使用遊標的人... :-)我以一種更有用的方式處理分頁我比如果我會使用遊標。預先感謝您的關注。此外,我想我會拼出來什麼,我試圖做的代碼位:
q = Item.all()
#orders it by highest index first which is how client handles items
q = q.order('-index')
#count is determined automatically but is at least 25 and not greater than 300
q = q.fetch(limit=count, offset=i)
編輯2:基於我決定試試我的存儲在內存緩存中的項目的意見,並盡一切我的過濾,排序,偏移等......在內存中。 Item
分組爲Category
,最多可容納1500個項目,並將每個Category
存儲在自己的密鑰下的memcache中。我能想到的唯一問題是每個Item
最糟糕的情況都是2kb大小。 Category
不太可能在其中的任何地方有1500 Items
,或者Item
將達到最差情況的大小,但如果是這樣,它將超過1mb的內存緩存限制。有關如何處理該問題的任何建議?此外,可能會有大約10 Categories
; memcache中的這麼多存儲是否會導致它更頻繁地刷新?最後,當我獲取Entities
或memcache是一個更好的解決方案時(Items
將被頻繁訪問,通常以小組(25-30))訪問時,是否值得使用偏移?
編輯3:我現在有一個引用項目的順序方式。每個項目都有一個id,它可以跨類別唯一地標識它,索引是一種非順序排序類別中的項目的方法,num是順序的,但對項目並不隱含(每次我將項目從內存緩存我通過索引順序,然後通過項目列表循環,分配的每一項NUM考慮到當前迭代次數),我想這是說的一個令人費解的方式:
for i in range(0, len(items)):
items[i]['num'] = i
編輯4:項目型號:
class Item(db.Model):
item_id = db.IntegerProperty()
index = db.IntegerProperty()
#I used StringProperty instead of ReferenceProperty because I'm a cheapo with memory
category = db.StringProperty()
我保持num
與模型分開,因爲與將其更新爲按順序添加和移除相關的成本。因此,我使用index
來維護項目的(非順序)順序,並且每次代表某個特定類別的項目的列表被踢出數據存儲區時,我會遍歷它們並向每個項目添加一個順序的「num
」 。因爲我的用戶界面完全是動態的(所有的AJAX;沒有頁面重新加載),我緩存每一個發送到瀏覽器的項目在JavaScript中,num
真的只爲客戶端(閱讀:瀏覽器)。服務器端我不一定需要順序的項目;在客戶端有一些需要它的功能,並且服務器對於非順序索引會很好。
我的問題的主要癥結似乎轉變成是否應該保留此模型,即將所有項目存儲在內存緩存中,或者直接從數據存儲中檢索項目。項目會被要求很多(我沒有確切的數量,甚至估計每秒多少次,但它應該是每秒要求的許多項目)。我知道無法準確確定這些項目在啓動之前會在memcache中存在多長時間,但是我能否認爲它不會每隔幾分鐘發生一次?因爲如果是別的,我覺得最好的方式是使用memcache,但我可能會錯過一些東西。哦,希望這將是最後的編輯之前,我偷的是SO的磁盤空間)
EDIT 5這麼多沒有更多的編輯...這是一個使用內存緩存時的時間複雜度我的計算圖表和數據存儲或者只是數據存儲(因爲我不確定它到底是什麼,所以省去了數據存儲的時間複雜性,現在閱讀BigTable文件來試圖找出它並不是太晚了,所以我只是假設它是在散列表上的操作相同)。這些都是最好的例子。對於memcache解決方案,最糟糕的情況是您需要添加N個數據存儲區讀取(因爲該類別中的所有項必須讀入memcache)。對於memcache和數據存儲解決方案,這個圖表不需要爲存儲或檢索數據(即排序,過濾器)做任何額外的工作。對於僅限memcache的解決方案,num
未存儲在數據存儲中。對於數據存儲區唯一的解決方案,這就是爲什麼添加或刪除(更新每個項目的num
)相關的額外成本。
n DS = number of DataStore operations
w = write
r = read
N = number of items in category (for Add and Remove this is the number before
the operation is performed)
c = count of items to read
o = offset
+------------------------------------------------------------------------------+
| Memcache | Datastore |
|------------------------------------------------------------------------------|
| | | | |
| Reads | O(o + c) | Reads | c DS r |
|-------+-------------------------------|-------+------------------------------|
| | | | |
|Reads w| O(o + c) |Reads w| o + c DS r |
|Offset | |Offset | |
|-------+-------------------------------|-------+------------------------------|
| | | | |
| Adds | 1 DS w + O(N) | Adds | 1 + N DS w & N - 1 DS r |
|-------+-------------------------------|-------+------------------------------|
| | | | |
|Removes| 1 DS rw + O(o + N) |Removes| N - o DS wr |
|-------+-------------------------------|-------+------------------------------|
| | | | |
| Edits | 1 DS rw + O(o) | Edits | 1 DS rw |
|-------+-------------------------------|-------+------------------------------|
所以現在的問題是,做爲內存緩存解決方案的時間差的複雜性超過附帶的數據存儲解決方案,除非內存緩存驅逐可能比數據存儲解決方案的內存緩存解決方案會導致更多的DS操作的可能性更DS操作(因爲每次物品從mecache中被逐出,我們必須執行N DS r
來重新填充內存緩存)。這一切都假設讀取發生得比在初始數據加載完成後在這個應用程序中寫入的情況要頻繁得多。
物品的排序是否改變?項目#1000總是在類別中的項目1000,還是會改變?如果它確實發生了變化,這種行爲的大概頻率是多少?你對偶爾返回陳舊的結果感到滿意嗎? – 2012-07-11 04:27:24
我根據其索引訂購了該類別內的物品。較新的項目具有較高的索引,我首先將它們呈現給用戶最高索引。如果項目被刪除,則索引將不會被重新計算,因此索引爲1000的項目可能是該類別中的第一個項目,最後一個項目或之間的任何項目。 – Eliezer 2012-07-11 04:35:12
我不知道我明白你在做什麼。您是否嘗試檢索單個項目(例如,數據存儲區中的第1000個項目),具有給定索引的項目(例如索引== 1000)或項目集合(例如第1000到1010個順序項目)? – 2012-07-11 05:17:18