#google-app-engine #google-cloud-datastore
#google-app-engine #google-облачное хранилище данных
Вопрос:
У меня возникли некоторые проблемы с хранилищем данных Google App engine. С тех пор, как была введена новая модель ценообразования, стоимость запуска моего приложения значительно возросла.
Причиной, по-видимому, являются «небольшие операции с хранилищем данных», на которые приходится более 20 миллионов операций в день!
У кого-нибудь была эта проблема, я не думаю, что я выполняю чрезмерное количество ключевых запросов, и у меня всего 5000 пользователей, с примерно 10-20 запросами в минуту.
Заранее спасибо!
Редактировать
Хорошо, получил некоторую статистику, это примерно через 3 часа. Вот что я вижу на своей панели мониторинга в разделе выставления счетов:
И вот некоторые статистические данные:
Очевидно, что существует довольно много вызовов datastore.get. Я начинаю думать, что проблема в моем дизайне. Эти данные соответствуют учетным записям. У каждого пользователя есть учетная запись, но учетная запись может быть одного из двух типов, для этого я использую композицию. Таким образом, каждый объект учетной записи имеет ссылку на свой объект субаккаунта. В результате, когда я выполняю поиск ближайших пользователей, это включает в себя выборку учетных записей с помощью запроса, а затем выполнение get для каждой учетной записи, чтобы получить ее вспомогательную учетную запись. Главный запрос на картинке статистики — это вызов, который получает 100 учетных записей, а затем должен выполнить get для каждой из них. Я бы подумал, что это очень легкий запрос, но, думаю, нет. И меня все еще смущает количество небольших операций с хранилищем данных, записываемых на моей панели мониторинга.
Комментарии:
1. Из любопытства, каким был ваш типичный ежемесячный счет до и после?
2. Моя ежедневная норма составляла 2 доллара, и я никогда не достигал этого. Сейчас это 5 долларов, и я превышаю его каждый день. Я думаю, мне пришлось бы увеличить до 9 долларов в день.
3. Извините, я тоже должен был спросить об этом, но используете ли вы memcache вообще?
4. Нет, я действительно не заглядывал в memcache. Я бы подумал, что хранилище данных может обрабатывать текущий объем данных по гораздо более разумной цене. Тем не менее, я запускаю не сайт, а серверную часть приложения, игры, поэтому она довольно сложна в обработке.
5. «Главный запрос на картинке статистики — это вызов, который получает 100 учетных записей, а затем должен выполнить get для каждой из них». Вы должны извлекать все 100 ключей одним пакетом, а не выполнять отдельные операции. Смотрите здесь для объяснения шаблона. Кроме того, вам определенно следует хранить объекты, к которым часто обращаются, в memcache, чтобы сократить время поиска в хранилище данных.
Ответ №1:
Обязательно используйте appstats, как предлагает Дрю; независимо от того, какую библиотеку вы используете, она расскажет вам, какие операции выполняют ваши обработчики. Наиболее вероятными виновниками являются запросы только для ключей и операции подсчета.
Комментарии:
1. Обратите внимание, что здесь мне приходится выполнять обычную операцию синхронизации, и я получал общее количество пользователей при каждой синхронизации. Итак, я кэширую это сейчас, и я вижу разницу. Приветствия!
Ответ №2:
Я бы посоветовал использовать AppStats (Python / Java) для профилирования вашего трафика и определения, какой обработчик генерирует больше всего операций с хранилищем данных. Если вы разместите код здесь, мы потенциально сможем предложить оптимизации.
Комментарии:
1. Я знаю, куда направляется большая часть моего трафика, и я использую ‘Siena’, библиотеку Java, которая работает с GAE. Я пройдусь по своему коду и попытаюсь выделить фрагменты, которые могут оказаться полезными.
2. AppStats настроен, обновит мой исходный пост, когда у меня будет больше информации. Спасибо.
Ответ №3:
Не сканируйте свое хранилище данных, используйте get (ключ) или get_by_id (идентификатор) или get_by_key_name (ключевое имя) как можно чаще.
Ответ №4:
Много ли у вас свойств ReferenceProperty в ваших моделях? Доступ к ним вызовет db.get для каждого свойства, если вы не выполните предварительную выборку. Это вызвало бы 101 запрос db.get.
class Foo(db.Model):
user = db.ReferenceProperty(User)
foos = Foo.all().fetch(100)
for f in foos:
print f.user.name # this triggers db.get(parent=f, key=f.user)
Комментарии:
1. С помощью Java API, который я использую, мне нужно вручную получить каждое свойство, на которое ссылается другой объект. Сейчас пытаюсь выполнять пакетную выборку, чтобы посмотреть, даст ли это мне необходимый импульс.
2. Проверьте эту запись в блоге, которую я написал, часть предварительной выборки: bravenewmethod.wordpress.com/2011/03/23 /…