2014-02-13 30 views
0

所以我有一個腳本可以加載從python pickle文件創建的數據。通過Django orm加載數據非常內存密集

dump_file = open('movies.pkl') 
movie_data = pickle.load(dump_file) 

@transaction.commit_manually 
def load_data(data): 
    start = False 
    counter = 0 
    for item in data: 
       counter += 1 
      film_name = item.decode(encoding='latin1') 
      print "at", film_name, str(counter), str(len(data)) 
      film_rating = float(data[item][0]) 
      get_votes = int(data[item][2]['votes']) 
      full_date = data[item][2]['year'] 
      temp_film = Film(name=film_name,date=full_date,rating=film_rating, votes=get_votes) 
      temp_film.save() 
      for actor in data[item][1]: 
       actor = actor.decode(encoding='latin1') 
       print "adding", actor 
       person = Person.objects.get(full=actor) 
       temp_film.actors.add(person) 
      if counter % 10000 == 0 or counter % len(data) == 0: 
        transaction.commit() 
        print "COMMITED" 

load_data(movie_data) 

所以這是一個非常大的數據集。它佔用了大量的內存,並減慢了抓取速度,過去我的解決方案是從我停止的地方重新啓動腳本,因此需要經過幾次運行才能將所有內容都保存到數據庫中。

我想知道是否有更好的方法來做到這一點(甚至在我的代碼中的優化會很好)除了寫入原始的sql輸入數據?我以前試過JSON裝置,它比這種方法更糟糕。

回答

1

如果movie_data的大小很大,您可能想先將它分成較小的文件,然後逐個迭代它們。 請記住釋放之前加載的pkl文件的內存或保留覆蓋相同的變量。 如果電影數據是一個列表,您可以通過片段迭代它們(例如movie_data = movie_data [1000:])來釋放1000條記錄的內存,以減少內存消耗隨着時間的推移

+0

movie_data是一個字典,它包含關於每部電影的信息列表,所以我可能會試圖將字典拆分爲多個部分。 – dl8

+0

爲什麼你要將這個龐大的數據集存儲在一個pickle而不是數據庫中? – lmc

+0

由於數據獲取方式的性質,將所有數據收集到一個pickle中,然後處理所有要放入數據庫的數據會更加方便。將來我可能會嘗試寫一些直接將其加載到數據庫中的東西,但目前這種方法更簡單。 – dl8

1

您可以使用bulk_create方法在QuerySet對象上在單個查詢中創建多重對象,它在Django 1.4中可用。請通過下面的文檔鏈接 -

您還可以優化你的代碼,通過打開該文件「與」 Python中的關鍵字。 「With」語句會自動關閉文件,執行with塊內的所有操作,因此它會爲您保留這些文件,並在您退出with塊時關閉這些文件。

+0

是的,這個腳本是前一段時間創建的,當時我不知道'與',現在我將添加它。我會測試bulk_create,看看它是否有幫助。 – dl8

+0

事實上,進一步閱讀它所說的「它不適用於多對多關係」的文檔,目前我已經與我的演員和電影模特合作過了。 – dl8