論壇、部落格等系統的內容欄位通常用 CLOB 儲存,極少參與 LIKE 查詢,且全文檢索建議用 Lucene 等專用引擎。這類大量文本資料壓縮率極高,若能透明壓縮入庫,可大幅節省儲存空間與 I/O 頻寬。
public class StringZip {
public static String zipString(String str) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
GZIPOutputStream os = new GZIPOutputStream(bos);
os.write(str.getBytes("UTF-8")); // 建議指定編碼
os.close();
bos.close();
byte[] bs = bos.toByteArray();
return new String(bs, "ISO-8859-1"); // 以單位節對應 Latin-1 保存二進位
} catch (Exception ex) {
return str; // 失敗回退原文
}
}
public static String unzipString(String str) {
try {
ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes("ISO-8859-1"));
GZIPInputStream is = new GZIPInputStream(bis);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = is.read(buf)) != -1) bos.write(buf, 0, len);
is.close(); bis.close(); bos.close();
return new String(bos.toByteArray(), "UTF-8");
} catch (Exception ex) {
return str;
}
}
}
在實體類別新增 ziped 標記欄位,於 Getter/Setter 內自動判斷壓縮與否:
private String content;
private boolean ziped;
public String getContent() {
return ziped ? StringZip.unzipString(content) : content;
}
public void setContent(String content) {
if (content == null || content.length() < 512) { // 短文本不壓縮
this.content = content;
this.ziped = false;
} else {
String compressed = StringZip.zipString(content);
if (compressed.length() >= content.length()) { // 壓縮後反而變大
this.content = content;
this.ziped = false;
} else {
this.content = compressed;
this.ziped = true;
}
}
}
一般文章、評論文本壓縮率可達 70%~90%,實際數值請依業務資料自行基準測試。CPU 開銷極低,換取儲存與網路頻寬收益顯著。