Приведу пример запроса, для которого я не могу понять, что еще делать:
Приложение представляет собой счет / статистика боулинга. Когда кто-то вводит свои баллы в расширенном режиме, вычисляется ряд характеристик, а также их баллы. Данные моделируются как:
Игра - участники, такие как имя, пользователь, ссылка на боулинг, счет Кадр - попадания кеглей для каждого шара, логические списки, для которых кегли были сбиты на каждом шаре, информация о траектории мяча (стойка, цель, куда он на самом деле попал), счет на этот кадр и т. д. GameStats - хранит рассчитанную статистику для всей игры, которая может быть объединена с другой игровой статистикой по мере необходимости для отображения статистики по группам игр.
Пример этой информации на практике можно найти в здесь.
Когда игра завершена и кадр обновлен, я должен обновить игру, кадр, каждый кадр после него и, возможно, некоторые до него (чтобы убедиться, что их результаты верны) и статистику. Эта операция всегда помечает монитор ЦП. Даже если игра не завершена и статистику вычислять не нужно, баллы и тому подобное необходимо обновить, чтобы показать пользователю прогресс в реальном времени, и поэтому они также помечаются. Среднее время процессора для этого обработчика составляет более 7000 мциклов, и он даже не отображает представление. Большинство людей ставят от 3 до 4 игр за серию - если они вводят свои результаты в реальном времени на дорожках, это примерно 1 запрос каждые 2–4 минуты, но если они записывают все и вводят позже, получается 30-40 игр. эти запросы делаются подряд.
Согласно запросу, модель данных для важных классов:
class Stats(db.Model):
version = db.IntegerProperty(default=1)
first_balls=db.IntegerProperty(default=0)
pocket_tracked=db.IntegerProperty(default=0)
pocket=db.IntegerProperty(default=0)
strike=db.IntegerProperty(default=0)
carry=db.IntegerProperty(default=0)
double=db.IntegerProperty(default=0)
double_tries=db.IntegerProperty(default=0)
target_hit=db.IntegerProperty(default=0)
target_missed_left=db.IntegerProperty(default=0)
target_missed_right=db.IntegerProperty(default=0)
target_missed=db.FloatProperty(default=0.0)
first_count=db.IntegerProperty(default=0)
first_count_miss=db.IntegerProperty(default=0)
second_balls=db.IntegerProperty(default=0)
spare=db.IntegerProperty(default=0)
single=db.IntegerProperty(default=0)
single_made=db.IntegerProperty(default=0)
multi=db.IntegerProperty(default=0)
multi_made=db.IntegerProperty(default=0)
split=db.IntegerProperty(default=0)
split_made=db.IntegerProperty(default=0)
class Game(db.Model):
version = db.IntegerProperty(default=3)
user = db.UserProperty(required=True)
series = db.ReferenceProperty(Series)
score = db.IntegerProperty()
game_number = db.IntegerProperty()
pair = db.StringProperty()
notes = db.TextProperty()
simple_entry_mode = db.BooleanProperty(default=False)
stats = db.ReferenceProperty(Stats)
complete = db.BooleanProperty(default=False)
class Frame(db.Model):
version = db.IntegerProperty(default=1)
user = db.UserProperty()
game = db.ReferenceProperty(Game, required=True)
frame_number = db.IntegerProperty(required=True)
first_count = db.IntegerProperty(required=True)
second_count = db.IntegerProperty()
total_count = db.IntegerProperty()
score = db.IntegerProperty()
ball = db.ReferenceProperty(Ball)
stance = db.FloatProperty()
target = db.FloatProperty()
actual = db.FloatProperty()
slide = db.FloatProperty()
breakpoint = db.FloatProperty()
pocket = db.BooleanProperty()
pocket_type = db.StringProperty()
notes = db.TextProperty()
first_pinfall = db.ListProperty(bool)
second_pinfall = db.ListProperty(bool)
split = db.BooleanProperty(default=False)


Несколько предложений:
Вы хотите получить все кадры из одной игры, соответствующие этим критериям, или все кадры из всех игр? Если бы первое, то линейный поиск был бы проще.
В любом случае, я думаю, вам определенно нужен способ интегрировать фреймы в основную сущность и уменьшить общее количество полей - удалить те, которые легко вычислить, из других. При кодировании объектов для хранилища данных возникают довольно высокие накладные расходы на каждое поле.
Я хотел бы найти кадры из всех игр (для пользователя) или определенного подмножества игр. В объекте Frame только 4 свойства могут быть вычислены из других, и они не обязательно тривиальны (например, is_split). Я думал, что GAE поощряет хранение большого количества данных?
Это так, но в виде множества объектов, организованных таким образом, что вы должны касаться как можно меньшего числа в запросе. Моя предложенная стратегия заключалась в том, чтобы хранить только все, что вам нужно проиндексировать, и все, что вам нужно для восстановления полного набора данных, а также все, что значительно дорого для расчета.
Причина, по которой я в итоге добавил класс статистики, заключалась в том, что когда у меня была лига с 16 неделями, каждая из которых имела 4 игры, вычисление статистики для всего этого приводило к чрезмерной загрузке процессора. Хммм ... Может мне просто нужно подождать увеличения платной квоты? Или посмотрите другой хостинг?
Или разбейте его на более мелкие запросы - не пытайтесь обрабатывать 64 игры за один запрос.
Какие-нибудь советы о том, как этого добиться?
Если ваше приложение AJAX-y, оно может отправлять меньший набор игр в каждом запросе - например, отправляя их, когда пользователь вводит их.
Я думал об использовании идеи битового поля для булавок, но это не очень удобно, по крайней мере, в GAE. Например, я хочу захватить все рамки, на которых я оставил некоторую форму размытия (шпилька, 2 булавки и 10 булавки стоят, а 3, 5 и 9 - нет).