Высоко масштабируемые теги в Google App Engine (Python)

У меня много (например) сообщений, отмеченных одним или несколькими тегами. Сообщение может быть создано или удалено, а также пользователь может выполнить запрос поиска для одного или нескольких тегов (в сочетании с логическим И). Первая идея, которая пришла мне в голову, была простой моделью

class Post(db.Model): #blahblah tags = db.StringListProperty() 

Реализация операций создания и удаления очевидна. Поиск более сложный. Для поиска N-меток он будет выполнять запросы N GQL, такие как «SELECT * FROM Post WHERE tags =: 1» и объединить результаты с помощью курсоров, и это имеет ужасную производительность.

Вторая идея состоит в том, чтобы отделить теги в разных объектах

 class Post(db.Model): #blahblah tags = db.ListProperty(db.Key) # For fast access class Tag(db.Model): name = db.StringProperty(name="key") posts = db.ListProperty(db.Key) # List of posts that marked with tag 

Он принимает теги от db по ключу (намного быстрее, чем принимать его с помощью GQL) и объединять его в памяти, я думаю, что эта реализация имеет лучшую производительность, чем первая, но очень часто используемые теги могут превышать максимальный размер, который допускал бы один объект хранилища данных , И есть еще одна проблема: хранилище данных может изменять один единственный объект только ~ 1 / сек, поэтому для часто используемых тегов у нас также есть узкое место с изменением латентности.

Какие-либо предложения?

Для дальнейшего допроса Ника. Если это логическое И использование нескольких тегов в запросе. Использовать теги = tag1 AND tags = tag2 … установить членство в одном запросе – это одна из ярких функций хранилища данных. Вы можете достичь результата в одном запросе.

http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html#Properties_With_Multiple_Values

Вероятно, возможное решение состоит в том, чтобы взять ваш второй пример и изменить его таким образом, чтобы разрешить эффективные запросы для больших наборов. Один из способов, который приходит на ум, состоит в том, чтобы использовать несколько объектов базы данных для одного тега и группировать их таким образом, чтобы вам редко приходилось получать больше нескольких групп. Если порядок сортировки по умолчанию (ну давайте просто называть его единственным разрешенным) по дате, затем заполните объекты группы тегов в этом порядке.

 class Tag(db.Model): name = db.StringProperty(name="key") posts = db.ListProperty(db.Key) # List of posts that marked with tag firstpost = db.DateTimeProperty() 

Когда вы добавляете или удаляете теги в группу, проверьте, сколько сообщений в этой группе, если пост, который вы добавляете, сделает сообщение более чем, скажем, 100 сообщений, разделите его на две группы тегов. Если вы удаляете сообщение, чтобы группа имела менее 50 сообщений, крайте некоторые сообщения из предыдущей или следующей группы. Если одна из соседних групп также имеет 50 сообщений, просто объедините их вместе. Когда вы публикуете сообщения по тегу (в порядке после даты), вам нужно получить только несколько групп.

Это не позволяет решить проблему с высоким требованием.

Подумав об этом, может быть, что вставки будут немного более спекулятивными. Получите последние записи группы тегов, объедините их и поместите новую группу тегов. Задержка транзакций на самом деле не может быть реальной проблемой.

Interesting Posts