June 10, 2021
데이터베이스에 신규 데이터를 넣어주기 위해서 엑셀 파일을 읽어 데이터베이스에 넣어주는 작업 중에 마주한 문제인데,
메모리및 IO 작업을 최소화하기 위해 chunk size 만큼 리스트에 Django model instance 변수를 담고 .bulk_create
를 수행했다.
당연히 chunk size에 도달하여 리스트를 초기화해주면 메모리가 해제될 거 같지만 그렇지 않았고, 메모리가 가득차서 곧 서버 장애로 이어졌다.
import pandas as pd
data = pd.read_excel(...)
models = []
for index, row in data.iterrows():
models.append(get_model_instance(model_class, row)
if len(models) == chunk_size:
model_class.objects.bulk_create(models)
models = []
else:
if models:
model_class.objects.bulk_create(models)
In [1]: User.__del__ = lambda x: print(id(x))
In [2]: l = []
In [3]: u = User.objects.first()
In [4]: id(u)
Out[4]: 4833674432
In [5]: l.append(u)
In [6]: u = User.objects.first()
In [7]: id(u)
Out[7]: 4848304192
In [8]: l.append(u)
In [9]: u = User.objects.first()
In [10]: id(u)
Out[10]: 4848129456
In [11]: l.append(u)
In [12]: l = []
In [13]: del u
In [14]: u = User.objects.first()
In [15]: u = None
4848386112
>>> class Test:
... def __del__(self):
... print(id(self))
...
>>> l = []
>>> t = Test()
>>> id(t)
4378831936 (1)
>>> l.append(t)
>>> t = Test()
>>> id(t)
4379975536 (2)
>>> l.append(t)
>>> t = Test()
>>> id(t)
4378420512 (3)
>>> l.append(t)
>>> l = []
4379975536 (2)
4378831936 (1)
(3)
은 아직 변수에 할당되어 있기 때문에 해제되지 않음
변수 스코프를 완전히 끊어버리면 된다.
In [1]: User.__del__ = lambda x: print("삭제!", id(x))
In [2]: def process():
...: l = []
...: for u in range(3):
...: u = User.objects.first()
...: print("생성!", id(u))
...: l.append(u)
...: print("함수 안녕!")
...:
In [3]: process()
생성! 5015568544
생성! 5015570848
생성! 5029692560
함수 안녕!
삭제! 5015570848
삭제! 5015568544
삭제! 5029692560