ユーザーがページをめくるアイテムのリストがあるアプリケーションがあります。私はインデックスフィールドを介してページングを処理しました(とにかく他の目的でそれが必要だったので、なぜそうしないのか考えました)。
私の問題は、「goto」機能を実装したいということです。ユーザーは、提供されているナビゲーションボタン(次と前)を使用してアイテムをページングする代わりに、アイテムに直接スキップできます。たとえば、「goto」ボックスに1000と入力して、1000番目のアイテムを表示することができます。n番目のアイテムとそのインデックスの間には断絶があります。インデックスは正しいことが保証されていますが、連続しているとは保証されていないため、インデックスでフィルタリングすることはできません。offset
のパラメータを使用することを考えましたfetch
が、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: コメントに基づいて、アイテムをmemcacheに保存し、フィルタリング、順序付け、オフセットなどのすべてをメモリに保存することにしました。は最大1500個のアイテムを保持できるItem
グループ化されており、それぞれを独自のキーでmemcacheに保存します。私が考えることができる唯一の問題は、それぞれが最悪の場合のシナリオのサイズが2kbになる可能性があるということです。aが1500に近い場所にある可能性は低く、最悪のシナリオサイズに達する可能性は低いですが、そうなると、1MBのmemcache制限を超えます。それを処理する方法について何か提案はありますか?また、約10個ある可能性があります。memcacheにこれだけ多くのストレージがあると、より頻繁にフラッシュされますか?そして最後に、私がフェッチするときにオフセットを使用することは価値がありますか?Category
Category
Item
Category
Items
Item
Categories
Entities
または、memcacheの方が優れたソリューションItems
ですか(通常は小グループ(25〜30)で非常に頻繁にアクセスされます)?
編集3: アイテムを順番に参照する方法ができました。各アイテムには、カテゴリ間で一意に識別するID、カテゴリ内のアイテムを非順次に並べ替える方法であるインデックス、および順次であるがアイテムに暗黙的ではないnumがあります(アイテムを引き出すたびにmemcacheインデックスで並べ替えてから、アイテムのリストを繰り返し処理し、各アイテムに現在の反復回数を指定して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
はアイテムの(非シーケンシャル)順序を維持するために使用し、特定のカテゴリのアイテムを表すdictのリストがデータストアから追い出されるたびに、それらを調べnum
て各アイテムにシーケンシャル""を追加します。num
私のUIは完全に動的であり(すべてAJAX、ページのリロードは一切ありません)、ブラウザーに送信されるすべてのアイテムをjavascriptでキャッシュするため、これは実際にはクライアント(読み取り:ブラウザー)専用です。サーバーサイド私は必ずしもアイテムの順番を並べる必要はありません。クライアント側にはそれを必要とする特定の関数があり、サーバーは非シーケンシャルインデックスで問題なく動作します。
私の質問の主な要点は、このモデルを保持する必要があるかどうか、つまり、カテゴリのすべてのアイテムをmemcacheに保存するか、データストアから直接アイテムを取得することに戻るかということになっているようです。アイテムはたくさん要求されます(正確な量や1秒間に何回の見積もりすらありませんが、1秒間に要求されるアイテムの数が多いはずです)。アイテムがキックアウトされる前にmemcacheにある時間を正確に決定する方法がないことは知っていますが、数分ごとに発生しないと想定できますか?それ以外の場合は、memcacheを使用するのが最善の方法だと思いますが、何かが足りない可能性があります。ああ、そしてうまくいけば、これがSOのディスクスペースをすべて盗む前の最後の編集になるでしょう;)
編集5これ以上の編集は必要ありません...これは、memcacheとデータストアまたはデータストアのみを使用した場合の時間計算量の計算のチャートです(データストアが何であるか正確にわからないため、データストアの時間計算量を省略しました。 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 |
|-------+-------------------------------|-------+------------------------------|
したがって、問題は、memcacheソリューションの時間計算量がデータストアソリューションに伴う潜在的により多くのDS操作を上回るかどうかです。ただし、memcacheエビクションがmemcacheソリューションでデータストアソリューションよりも多くのDS操作を引き起こす可能性がある場合を除きます(アイテムがmecacheから削除された場合N DS r
、memcacheを再設定するために実行する必要があります)。これはすべて、最初のデータの読み込みが行われると、このアプリケーションでは書き込みよりも読み取りがはるかに頻繁に発生することを前提としています。