我有一个查询返回大约 600 万行,这太大了,无法在内存中一次处理。
每个查询都返回一个 Tuple3[String, Int, java.sql.Timestamp]。我知道字符串永远不会超过 20 个字符,UTF8。
我怎样才能计算出这些元组之一的最大大小,更一般地说,我怎样才能近似这样的 scala 数据结构的大小?
我正在使用的机器上有 6Gb。但是,正在使用 scala-query 从数据库中将数据读取到 scala 的列表中。
我有一个查询返回大约 600 万行,这太大了,无法在内存中一次处理。
每个查询都返回一个 Tuple3[String, Int, java.sql.Timestamp]。我知道字符串永远不会超过 20 个字符,UTF8。
我怎样才能计算出这些元组之一的最大大小,更一般地说,我怎样才能近似这样的 scala 数据结构的大小?
我正在使用的机器上有 6Gb。但是,正在使用 scala-query 从数据库中将数据读取到 scala 的列表中。
Scala 对象遵循与 Java 对象大致相同的规则,因此有关这些的任何信息都是准确的。 这是一个来源,至少对于 32 位 JVM 来说似乎是正确的。(64 位 JVM 每个指针使用 8 个字节,这通常会产生 4 个字节的额外开销加上每个指针 4 个字节的开销——但如果 JVM 使用压缩指针可能会更少,我认为现在默认情况下它会这样做。)
我假设一台没有压缩指针的 64 位机器(最坏情况);然后 aTuple3
有两个指针(16 个字节)加上一个Int
(4 个字节)加上对象开销(~12 个字节)四舍五入到最接近的 8 或 32 个字节,加上一个额外的对象(8 个字节)作为非专用版本的存根的Int
。(遗憾的是,如果您在元组中使用原语,它们会比使用包装版本时 占用更多的空间。)。String
是 32 字节,IIRC,加上数据的数组,即 16 加上每个字符 2。 java.sql.Timestamp
需要存储几个Long
s (我认为是),所以这是 32 个字节。总而言之,它大约是 120 个字节加上每个字符两个,大约 20 个字符是 160 个字节。
Alternatively, see this answer for a way to measure the size of your objects directly. When I measure it this way, I get 160 bytes (and my estimate above has been corrected using this data so it matches; I had several small errors before).
你有多少内存可供使用?三元组的 600 万个实例真的不是很多!
每个引用都有 4 或 8 个字节的开销,具体取决于您运行的是 32 位还是 64 位(没有压缩的“oops”,尽管这是 JDK7 中 32Gb 以下堆的默认设置)。
所以你的三元组有 3 个引用(由于专业化可能会有额外的引用 - 所以你可能会得到 4 个引用),你Timestamp
是一个围绕 a long
(8 个字节)的包装器(引用)。您Int
将是专门的(即底层int
),因此这又产生了 4 个字节。字符串为 20 x 2 字节。所以你基本上有一个每行远低于100 字节的最坏情况;所以每 kb 10 行,每 Mb 10,000 行。因此,您可以在 1 Gb 以下的堆中轻松处理 600 万行。
坦率地说,我认为我在这里犯了一个错误,因为我们每天在这个空间中舒适地处理大约 20 个字段(包括小数、字符串等)的几百万行。