2011-03-14 23 views
1

我有一個擁有幾百萬個對象的模型。每個對象代表一個公司發出/接收的呼叫。如何優化使用帶有列表的查詢集

爲了簡化,我們假設這個模型Call有這些字段:
calldate,context,channel。

我的目標是瞭解每月當天的每個小時(每小時加載)發出和接收的平均呼叫數。問題是:我需要分別找到port1port2

截至目前,我的代碼工作正常,除了它需要大約1整整一分鐘給我的結果4個月的範圍,我看起來效率非常低。

我已經做了一些簡單的分析,並發現延長正在處理時間99%左右:

queryset = Call.objects.filter(calldate__gte='SOME_DATE') 
port1, port2 = [],[] 
port1.extend(queryset.filter(context__icontains="e1-1")) 
port2.extend(queryset.filter(context__icontains="e1-2")) 
channels_in_port1 = ["Port/%d-2" % x for x in range(1,32)] 
channels_in_port2 = ["Port/%d-2" % x for x in range(32,63)] 

for i in channels_in_port1: 
    port1.extend(queryset.filter(channel__icontains=i)) 
for i in channels_in_port2: 
    port2.extend(queryset.filter(channel__icontains=i)) 

port1與port2有15萬左右,現在的對象結合。

只要我有端口1端口2的所有呼叫,我很好去。代碼的其餘部分基本上是一些for循環端口1端口2,總結和根據小時/日/月平均呼叫。平凡的東西。

我試圖通過使用itertools.chain並鏈接查詢集來避免使用任何「擴展」。但是,這使得處理時間轉移到我爲循環計算每小時負載的重要部分。

任何替代品?更好的方法來過濾查詢集?
非常感謝!

+0

你可以發佈你的模型的代碼? – demux 2011-03-15 00:20:51

回答

0

我認爲你的問題是與第二套擴展,即那些在for循環,而不是第一個。 (第一種是完全沒有必要的,無論如何:不是先定義一個空的列表然後再擴展它,你可以做port1 = list(queryset.filter(context__icontains="e1-1"))。)

無論如何,總結一下我認爲你想要做的事情:得到所有Call對象爲特定的日期,在兩個街區根據對channel價值:一是它包含的值從0到31,另一個是32和62

好像你可以用做之間的值只是兩個查詢,根本沒有任何擴展:

port1 = queryset.filter(channel__range=["Port/1-2", "Port/31-2"]) 
port2 = queryset.filter(channel__range=["Port/1-32", "Port/31-62"]) 

這是不是做你想要的?

編輯迴應評論但是這只是隨後的兩個查詢,您可以延長,或連接。您發佈的代碼存在的問題是您正在爲每個端口進行查詢和擴展操作,這一定會很昂貴。如果你只做一個,再加上一個擴展/ concat,那將會便宜得多。

+0

是的,我知道第一部分是不必要的,但將查詢集轉換爲列表幾乎與擴展它的處理時間大致相同。無論是哪種情況,這裏都沒有關係。 :) 第二部分,使你提到的兩個查詢不起作用,這是爲什麼:port1應該是一個列表,其中包含具有已定義通道範圍的兩個Call對象,並調用對象,其中字段「context」爲「e1-1 」。這兩個不在一起。我不能只是鏈式過濾器。我可能不得不考慮像Aaron提到的集合函數,或者也許只是把它分成更多的列表... – chiurox 2011-03-15 15:06:53

+0

@chiurox:看看我上面的編輯。 – 2011-03-15 15:40:36