2011-12-25 83 views
1

我有一個關於DB/memcached用法的問題。我在數據庫中有一系列問題,按級別劃分(每級約1000個問題)。對於每個步驟中的每個用戶,我需要隨機選擇一個指定級別的問題。我使用標準的Django的ORM使用此查詢選擇+隨機行:memcached與隨機選擇數據庫

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的問題組中的問題的編號。現在找我建立一個隨機密鑰隨機問題:

鍵= STR(水平)+ '_' + STR(INT(random.random()* num_of_questions_by_level)

優點:獲得的1000個隨機問題大約是10倍快,比DB

缺點:初始高速緩存的人口是非常緩慢的

+0

正如我在我的回答中指出的那樣,問題在於你無法有效地使用memcached。不要加載所有的問題。當你用你的隨機密鑰加載一個特定的問題時,首先嚐試從緩存中獲取它,如果它沒有到那個問題的數據庫中並且下一次將它放入緩存中。 – Ravenex 2011-12-26 13:59:52

回答

2

商店他們在連續的ID號的數據庫,然後簡單收拾介於0和按鍵的數量隨機數再檢查memcached的密鑰,如果它返回的問題使用它,如果不從數據庫中拉出來,並將其放入memcached中以備下次使用。

如果您刪除問題並因此在序列中缺少ID,但是可以解決此問題,例如,如果不是使用ID,而是選擇數據庫中的X項目,然後選擇這些問題確實會改變您清除memcached的情況,從而刷新數據。