memcached与数据库进行随机选择

时间:2011-12-25 22:26:43

标签: django performance design-patterns memcached

我对DB / memcached的使用有疑问。我在数据库中有一系列问题,按级别划分(每级约1000个问题)。对于每个步骤的每个用户,我需要随机选择一个指定级别的问题。我使用此查询使用标准django的ORM select + random行:

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是level,n是级别为l的问题组中的问题编号。现在找一个随机问题,我建立一个随机密钥:

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

专业人士:获得1000个随机问题比从DB

快10倍

缺点:初始缓存人口非常缓慢

1 个答案:

答案 0 :(得分:2)

将它们存储在具有顺序ID号的数据库中,然后只需在0和键数之间选择一个随机数,然后检查memcached是否为密钥,如果它返回问题则使用它,如果不从数据库中取出它并将其放入在memcached中供下次使用。

如果您删除问题,这将使您遇到问题,因此序列中缺少ID但是可以克服此问题,例如,如果不是使用ID,而是选择数据库中的X项,然后问题会改变你清除memcached,以便数据得到刷新。