Memcached против базы данных для случайного выбора - PullRequest
1 голос
/ 26 декабря 2011

У меня есть вопрос об использовании БД / memcached. У меня есть ряд вопросов в базе данных, разделенных по уровням (около 1000 вопросов на уровень). Для каждого пользователя на каждом шаге мне нужно выбрать один вопрос для заданного уровня случайным образом. Я использую стандартный django ORM выбор + случайную строку, используя этот запрос:

question = Question.objects.all().filter(level=1).order_by('?')[0]

После анализа файлов журнала я увидел, что около 50% времени запросов к БД тратится на выбор вопросов. Я пытался использовать memcached для этого. Из-за случайного выбора это не очевидно, я не могу использовать его как хранилище ключ-значение для пар question_id-question. Поэтому я решил разделить вопросы по уровням, сохранить их в memcached, после чего выбрать группу вопросов из memcached и выбрать случайный с использованием python, например:

for level in ...:
    questions_by_level = [q for q in questions if q.level == level]
    cache.set('questions' + str(level), questions_by_level)

и когда мне нужен вопрос:

questions = cache.get('questions' + str(level))
question = choice(questions)

Я запрограммировал memcached на той же машине, и, таким образом, получаю 1000 вопросов примерно в 2,5 раза медленнее, чем из базы данных. Вероятно, это потому, что из memcached выбрано 1000 объектов, десериализовано в python и выбрано случайное. Можно ли выбрать другую стратегию использования кеша в этой ситуации? Вопросы обновляются редко, так что неплохо бы иметь кеш с моей точки зрения. Благодаря.

UPD : одно решение, которое я обнаружил сам. Для каждого вопроса создайте строковый ключ следующим образом: l_n, где l - уровень, а n - номер вопроса в группе вопросов с уровнем l. Теперь, чтобы найти случайный вопрос, я строю случайный ключ:

key = str (level) + '_' + str (int (random.random () * num_of_questions_by_level)

плюсы: получение 1000 случайных вопросов примерно в 10 раз быстрее, чем из БД

минусы: начальное заполнение кэша очень медленное

1 Ответ

2 голосов
/ 26 декабря 2011

Сохраните их в базе данных с последовательными номерами идентификаторов, а затем просто выберите случайное число от 0 до количества ключей, затем проверьте memcached для ключа, если он возвращает вопрос, используйте его, если не вытащите его из базы данных, и поместите егов memcached для следующего использования.

Это вызовет у вас проблемы, если вы удалите вопросы, и поэтому в последовательности отсутствуют идентификаторы, но эту проблему можно преодолеть, например, если вместо использования идентификаторов вместо этого выбратьэлемент X в базе данных, а затем, когда вопросы меняются, вы очищаете memcached, чтобы данные обновлялись.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...