1 回答

TA貢獻1811條經驗 獲得超5個贊
通常,您可以使用 Java 的檢測功能來確定運行時的內存消耗。
然而,由于各種原因,確定實際內存消耗并不總是那么容易,其中一些原因是:
框架、庫甚至 JVM 可能會創建數據或緩存的副本并重用它
查詢可能返回不同大小的結果,尤其是在使用 VARCHAR 等可變長度列類型時。您必須讀取該數據才能確定相應對象的實際大小
某些對象可能被多個其他對象引用,因此它們的大小可能會被錯誤地包含在內(例如,如果使用某些枚舉常量,則可能會計入對象大小,但它實際上不會增加增量,因為它很可能已經被加載) 。
此外,在大多數業務應用程序中,您無需費心確定一段代碼導致的確切內存消耗。原因也有多種,例如:
內存很便宜,因此如果遇到問題,(至少暫時)增加可用內存通常比(微)優化一段代碼更容易。
由于情況的變化(例如活躍用戶數量、數據變化等),系統使用和負載通常無法預測。
JVM 通常能夠有效地使用垃圾收集來回收內存以用于其他用途。
但這并不意味著您不應該考慮內存使用情況,例如,您真的需要同時在內存中存儲所有 10k 行嗎?您需要這些數據多長時間?您將如何處理這些數據?
話雖如此,粗略估計內存消耗通常很有幫助,并且在可能返回大量字符串的查詢的情況下,您應該估計最壞的情況,即假設最大長度字符串。
為此,您需要了解行將包含的內容,例如是否是整數、Integer
實例或可能有多少列。此外,您至少需要知道數據類型的內存要求,即我們不考慮任何緩存、重復、開銷等。Long
BigInteger
ResultSet
Java 對象的大小取決于多種因素,例如您使用的是哪個 JVM,是 32 位還是 64 位 JVM 等。各種來源表明,對象的內存消耗可以從對象標頭(通常是大小為 12 個字節)和對象字段的大小。
使用它,我們假設Integer
大小為 16 字節(12b 標頭和 4b?int
),Date
將是 24 字節(12b 標頭,8bfastTime
和 4bcdate
引用),字符串將是 12b 標頭,4b char[] 引用,8b 其他字段, 12h char[] 標頭和字符本身的 2*length 字節(或總共 36 + 2* 長度)。
因此,假設您的 85 列被分成 20 個整數、10 個日期和 55 個最大長度為 256 字節的字符串。一行至少需要20?* 16 + 10 * 24 + 55 * 548 = 30700 字節。因此,10k 行需要 307000000 字節或大約 300 MB(當所有字符串都達到最大長度時)。
如果我復制整個數據并將其保存在文件中,對于 8 列的 10,000 條記錄,它僅顯示 604 KB。
讓我們也稍微分解一下:
604 KB 為 618496 字節(1024 為 1 KB)
除以 10k,平均每行得到 61.8 字節
除以 8,每列得到 7.7 個字節(如果我們不考慮任何行或列分隔符)
讓我們將其四舍五入為每列 8 個字節,并假設您的文本文件是 Latin-1 編碼的(因此每個字符 1 個字節),因此每個文本列平均有 8 個字符,這非常短
在更簡單的計算中,如果我們使用與上述相同的假設,604KB 意味著您的數據將包含大約 604k 個字符,在 Java 中僅字符數據就需要 1208k 字節(或大約 1.2 MB)。再加上 80k 字符串的開銷,即 36 字節 * 80k,大約多出 2.8 MB,因此數據在內存中需要大約 4 MB。