2012-06-26 2 views
6

6 백만 행을 반환하는 쿼리가 있는데, 너무 커서 메모리에서 한 번에 모두 처리 할 수 ​​없습니다.어떻게 데이터 구조의 크기를 스칼라로 근사 할 수 있습니까?

각 쿼리는 Tuple3 [String, Int, java.sql.Timestamp]를 반환합니다. 나는 그 문자열이 결코 약 20 자 (UTF8) 이상이라는 것을 안다.

이 튜플 중 하나의 최대 크기를 계산하는 방법은 무엇입니까? 더 일반적으로 이처럼 스칼라 데이터 구조의 크기를 어떻게 계산할 수 있습니까?

내가 사용하고있는 컴퓨터에서 6Gb가 있습니다. 그러나 스칼라 목록을 스칼라 목록에 사용하여 데이터를 데이터베이스에서 읽는 중입니다.

답변

6

스칼라 개체는 Java 개체와 거의 동일한 규칙을 따르므로 그 정보는 정확합니다. Here is one source, 적어도 32 비트 JVM의 경우 거의 대부분의 것 같습니다. (64 비트 JVM은 포인터 당 8 바이트를 사용합니다. 일반적으로 4 바이트의 여분의 오버 헤드와 포인터 당 4 바이트를 사용합니다. 그러나 JVM이 압축 된 포인터를 사용하면 더 적을 수 있습니다. 기본적으로 압축 포인터가 사용됩니다.)

압축 된 포인터가없는 64 비트 컴퓨터를 가정합니다 (최악의 경우). Tuple3에는 가장 가까운 8 또는 32 바이트로 반올림 한 오브젝트 오버 헤드 (~ 12 바이트)에 더하여 Int (4 바이트)에 더하여 두 개의 포인터 (16 바이트)와 비 오브젝트 오브젝트의 스텁으로서의 여분 오브젝트 (8 바이트) 전문 버전 Int입니다. (슬프게도, 튜플에있는 프리미티브를 사용하는 경우, 래핑 된 버전을 사용할 때보 다 이 더 많이 공간을 차지합니다.). String은 32 바이트, IIRC, 문자 당 16 + 2 데이터 배열입니다. java.sql.TimestampLong을 저장할 필요가 있습니다 (나는 생각합니다), 32 바이트입니다. 모두 말해서, 문자 당 120 바이트 + 2 바이트의 순서이며 ~ 20 바이트는 ~ 160 바이트입니다.

또는 개체의 크기를 직접 측정하는 방법은 this answer을 참조하십시오. 이 방식으로 측정하면 160 바이트가됩니다 (위의 예상치가이 데이터를 사용하여 수정되어 일치하므로 몇 가지 작은 오류가있었습니다).

+0

좋은 점은 문자열과 객체 오버 헤드의 여분의 오버 헤드를 잊어 버렸습니다. 아직도, 그것은별로 데이터가 아닙니다. –

+0

왜 문자열 배열의 문자 당 24 더하기 2입니까? IIRC 배열은 비 배열의 경우 8 바이트 대 4 바이트이고 요소가 포함됩니다. –

+0

@ DanielC.Sobral - 64 비트 머신에서 16 바이트 인 객체 오버 헤드와 길이가 있으므로 약간 벗어났습니다. –

2

얼마나 많은 메모리를 가지고 있습니까? 6 백만 인스턴스의 트리플은 실제로 그렇게 많지 않습니다!

각 참조에는 32 비트 또는 64 비트 (압축 된 "oops"가없는 경우)가 32GB 미만의 힙에 대한 JDK7의 기본값이지만 실행 중인지 여부에 따라 4 바이트 또는 8 바이트의 오버 헤드가 있습니다.

트리플이 3 개의 참조를 포함하므로 (전문화로 인해 추가 참조가있을 수 있으므로 4 개의 참조를 얻을 수 있음) Timestamplong (8 바이트) 주위의 래퍼 (참조)입니다. Int은 전문화되며 (즉, 기본 int), 이로 인해 또 다른 4 바이트가 생성됩니다. String은 20 x 2 바이트입니다. 따라서 기본적으로 의 최악의 경우는 행 당 100 바이트입니다. 그래서 kb 당 10 개의 행, Mb 당 10,000 개의 행. 따라서 1Gb 미만의 힙에서 600 만 행을 편안하게 처리 할 수 ​​있습니다.

솔직하게이 공간에서 약 20 개의 필드 (십진수, 문자열 등 포함)를 매일 수백만 행 처리하기 때문에 나는 실수를 저질렀다고 생각합니다.

+0

추측이 필요하십니까? – matanster

관련 문제