Skip to content
isdnetworks
Go back

결합키 제거는 교환이다

(수정됨)

pandas 집계 배치의 메모리가 기가바이트 단위로 ECS 태스크 한계에 가까웠다. 원인 중 하나가 df.channel + '|' + df.sku 로 이어 만든 결합키 컬럼이었다.

Table of contents

Open Table of contents

원인 — 상속되는 무게

결합키를 만들어 두면 groupby('key') 한 컬럼으로 그룹핑할 수 있어 코드가 짧아진다. 문제는 그 컬럼이 백만 행 넘는 DataFrame 에 붙어 있고 object 문자열이라 memory_usage(deep=True) 로 재면 무겁다는 점이었다.

거기서 파생된 슬라이스 셋이 그 컬럼을 그대로 상속하고 있었다. 하나를 지우면 넷이 줄어들므로 상속 관계를 보고 파급이 큰 것부터 골랐다.

주의 — 바뀐 반환 형태

groupby('key') 를 groupby(['channel', 'sku']) 로 바꿨는데 결과는 같아야 하지만 반환 형태가 달랐다. idxmax() 가 원래는 위치 인덱스를 주다가 MultiIndex 에서는 튜플을 돌려줬다.

그래서 필요한 성분만 꺼내는 처리를 추가했다. 그룹 축이 바뀌면 반환 형태가 바뀌고 그것을 안 보면 조용히 틀린 값이 흘러간다.

검증 — 동점 처리의 확인

또 하나 확인할 것이 최댓값이 여럿일 때의 선택이었다. pandas 공식 문서대로 idxmax() 는 최댓값의 첫 출현 위치를 돌려주는데 어느 것이 첫 번째인지는 정렬 순서에 달렸다.

결합키가 두 컬럼을 이어 만든 것이므로 한 그룹 안에서는 양쪽 다 같은 순서가 되어 동작이 같다고 판단했다. 다만 이것은 추론이고 정렬을 전부 확인한 것이 아니라 수만 개 키 중 하나라도 다르면 assert_frame_equal() 검사기가 잡는다고 적고 진행했으며 검사는 통과했다.

이득만은 아닌 변경

메모리는 줄었지만 공짜가 아니었다. 그룹핑은 내부적으로 키를 정수로 바꾸는데 두 컬럼이면 두 번 하고 그룹핑이 여러 번 나오면 매번 다시 한다.

즉 CPU 가 늘어난다. 그래서 메모리만 보지 않고 time.perf_counter() 로 소요 시간도 함께 재면서 결합키를 하나씩 제거할 때마다 단계별로 기록했다. 한꺼번에 바꾸면 어느 것이 얼마나 줄였는지 알 수 없다.

판단 기준 — 맥락이 정한 방향

두 가지 방법이 있었는데 결합키를 두고 태스크 memory 를 올리는 것과 결합키를 없애 CPU 를 더 쓰는 것이다. 뒤쪽을 골랐다. 이유는 하루 한 번 10분쯤 도는 배치라 수 초 늘어나는 것은 아무 문제가 아니라서다. 대신 groupby 마다 두 컬럼을 정수화하는 비용을 감수했다.

기가바이트 단위를 줄이는 것은 한계를 넘느냐 마느냐를 가르므로 의도한 방향의 교환이었다. 초당 수백 번 도는 API였으면 같은 변경이 반대 결론이 되므로 결합키를 없애는 것이 좋다는 일반 규칙은 없다.

정리


Share this post on:

Previous Post
보낼 URL의 부재
Next Post
밖에서 다시 받아 채운 값