如何在Oracle中查找SQL查询中返回的记录的内存大小?

wvmv3b1j  于 2023-05-16  发布在  Oracle
关注(0)|答案(1)|浏览(419)

我正在执行一个返回10,000条记录的查询。

SELECT * FROM employee WHERE id < 11000;

返回的数据由85列组成(varchar,date,no.)。(我还有另一个类似的查询,得到的数据只有10列(varchar)。
在Oracle中有什么方法可以找到这个结果集的数据大小吗?像加载的数据将是100 MB或200 MB

要求:实际上我需要加载内存中的所有记录;在Java中进行一些处理。因此,我需要检查数据的大小,使用Oracle中的一些先决条件或任何其他适当的方式,你可以建议检查相同的?(我有生产许可证。所以我将在检查数据大小后实现逻辑)。

这种预检查只是为了避免Java中的Out of memory异常。
如果我复制整个数据并将其保存在文件中,则对于具有8列的10,000条记录,仅显示604 KB。记忆中是否也有同样的意志?

polhcujo

polhcujo1#

通常,您可以使用Java的插装功能来确定运行时的内存消耗。有关这方面的一些信息,请看这里:

但是,由于各种原因,确定实际内存消耗并不总是那么容易,其中一些原因是:

  • 框架、库甚至JVM都可以创建数据或缓存的副本并重用它
  • 查询可能返回不同大小的结果,特别是在使用VARCHAR等可变长度列类型时。您必须读取这些数据来确定相应对象的实际大小
  • 一些对象可能被多个其他对象引用,因此它们的大小可能会被错误地包含(例如如果使用了某个枚举常量,则可能会计入对象大小,但实际上不会增加,因为它很可能已经被加载了)。

此外,在大多数业务应用程序中,您不需要费心确定一段代码导致的确切内存消耗。同样有各种原因,例如:

  • 内存是廉价的,因此如果您遇到问题,通常(至少暂时)增加可用内存比(微)优化一段代码更容易。
  • 由于情况不断变化(例如:活动用户数、数据变化等)
  • JVM通常能够有效地使用垃圾收集来回收内存用于其他事情。

这并不意味着你不应该考虑内存使用,例如。你真的需要一次在内存中存储所有的10 k行吗?你需要这些数据多久,你在用它做什么?
也就是说,粗略估计内存消耗通常是有帮助的,在查询可能返回大量字符串的情况下,您应该估计最坏的情况,即假设最大长度字符串。
要做到这一点,你需要一些关于你的行将包含什么的知识,例如。无论是整数IntegerLong还是BigInteger示例,或者可以有多少列。此外,您至少需要知道数据类型的内存需求,即我们不考虑任何缓存、复制、ResultSet的开销等等。
Java对象的大小取决于各种因素,例如:你使用的是哪个JVM,是32位还是64位JVM等等。各种来源都指出,对象的内存消耗可以从Object头(通常规定为12字节大小)和对象字段的大小计算出来。
使用它,我们假设Integer的大小为16字节(12 b报头和4 b int),Date将是24字节(12b header,8b fastTime and 4b cdate reference),String would be 12b header,4b char[] reference,8b other fields,12 h char[] header和2*length字节用于字符本身(或总共36 + 2 * length)。
因此,假设您的85列被拆分为20个整数,10个日期和55个最大长度为256字节的字符串。一行需要 * 至少 * 20 * 16 + 10 * 24 + 55 * 548 = 30700字节。因此,10 k行将需要307000000字节或大约300 MB(当所有字符串都处于最大长度时)。
如果我复制整个数据并将其保存在文件中,则对于具有8列的10,000条记录,仅显示604 KB。
让我们把它也分解一下:

  • 604 KB将是618496字节(1024是1 KB)
  • 将其除以10 k,平均每行得到61.8字节
  • 将其除以8,每列得到7.7字节(如果不考虑任何行或列分隔符)
  • 让我们四舍五入到每列8字节,让我们假设您的文本文件是拉丁语-1编码的(所以每字符1字节),因此每个文本列平均有8个字符,这是相当短的

在一个更简单的计算中,如果我们使用与上面相同的假设,604 KB将意味着您的数据将由大约604 k个字符组成,在Java中仅字符数据就需要1208 k字节(或大约1.2MB)。再加上80 k字符串的开销,即36字节 * 80 k,大约多2.8MB,因此数据将需要大约4 MB的内存。

相关问题