Слияние кэшированных GQL-запросов вместо использования IN - PullRequest
1 голос
/ 15 апреля 2011

Я создаю фид, который объединяет комментарии многих пользователей, поэтому ваш фид может быть из комментариев user1 + user2 + user1000, тогда как мой может быть user1 + user2.Итак, у меня есть строка:

some_comments = Comment.gql("WHERE username IN :1",user_list)

Я не могу просто запоминать всю вещь целиком, поскольку у всех будут разные каналы, даже если каналы для user1 и user2 будут общими для многих зрителей.Согласно документации :

... оператор IN выполняет отдельный базовый запрос хранилища данных для каждого элемента в списке.Возвращенные объекты являются результатом перекрестного продукта всех базовых запросов хранилища данных и дедуплицированы .Для каждого отдельного запроса GQL допускается не более 30 запросов к хранилищу данных.

Существует ли библиотечная функция для объединения некоторых отсортированных и кэшированных запросов, или мне нужно:

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

Ответы [ 2 ]

2 голосов
/ 15 апреля 2011

Нет ничего встроенного, чтобы сделать это, но вы можете сделать это самостоятельно, с одной оговоркой: если вы выполните запрос in и вернете 30 результатов, это будет 30 записей, которые сортируют по наименьшей степени согласно вашим критериям сортировкипо всем подзапросам.Однако если вы хотите собрать набор результатов из отдельных кэшированных запросов, то вам придется кэшировать столько результатов для каждого пользователя, сколько и всего набора результатов (например, 30), и отбрасывать большинство этих результатов, или вы 'нам придется хранить меньше результатов для каждого пользователя, и согласиться с тем, что иногда вы будете отбрасывать новые результаты от одного пользователя в пользу более старых результатов от другого.

Тем не менее, вот как вы можете это сделать:

  1. Выполните memcache.get_multi, чтобы получить кэшированные наборы результатов для всех пользователей
  2. Для каждого пользователя, у которого нет кэшированного набора результатов, выполните отдельный запрос, выбирая наибольшее количество результатов.тебе нужно.Используйте memcache.set_multi для кэширования наборов результатов.
  3. Выполните объединение слиянием для всех наборов результатов и возьмите первые n результатов в качестве окончательного набора результатов.Поскольку имя пользователя предположительно не является полем списка (например, у каждого комментария есть один автор), вам не нужно беспокоиться о дубликатах.

В настоящее время in запросы выполняются последовательно, поэтомуподход не будет медленнее, чем выполнение запроса in, даже если ни один из результатов не будет кэширован.Это может измениться в будущем, хотя.Если вы хотите улучшить производительность сейчас, вы, вероятно, захотите использовать проект Guido NDB , который позволит вам выполнять все подзапросы параллельно.

1 голос
/ 15 апреля 2011

Вы можете использовать memcache.get_multi(), чтобы увидеть, какой из каналов пользователя уже находится в memcache.Затем используйте set().difference() в исходном списке пользователей против списка пользователей, найденного в memcache, чтобы узнать, какие из них не были получены.Затем, наконец, извлеките пропущенные пользовательские каналы из хранилища данных в пакетном режиме.

Оттуда вы можете объединить два списка и, если он не слишком длинный, отсортировать его в памяти.Если вы работаете над чем-то Ajaxy, вы можете передать сортировку клиенту.

...