2012-07-27 29 views
0

我正在使用Snappy-java來編碼JSON數據,我想將結果存儲在數據庫中的varchar列中。
該數據庫是一個具有ISO-8859-1編碼的oracle數據庫。
我在插入數據時遇到編碼問題。似乎某些字符不被Oracle識別。在varchar列中存儲活潑的編碼數據

在插入壓縮數據之前,我找到了一個解決方法,在壓縮數據上使用Base64編碼。然後我就可以找回它就好:)

的問題,那就是Base64編碼增加了數據,我再存儲,特此減少與斯納皮所節省的長度...

所以我的問題是:我怎樣才能存儲這些數據,而不用在Base64中進行編碼? 我想使用varchar的原因是因爲我希望能夠使用oracle索引訪問表而無需訪問表(性能肯定是問題)。

我也嘗試過其他壓縮算法,但它們似乎都有同樣的問題。 我也看過yEnc,但找不到任何java編碼器。此外,我不確定我是否瞭解與yEnc一起列出的所有問題,所以我有點不情願使用它。

非常感謝您的幫助!

+0

您是否試圖索引包含二進制數據的列?聽起來你的設計有問題。您將不得不放棄壓縮或索引。 – 2012-07-27 15:26:47

回答

0

謝謝大家的幫忙!

我終於找到了解決方法。 由於我存儲字節而不是字符,因此我將使用BLOB來存儲數據。 BLOB的問題是它不能被索引。 另一種方法是使用RAW類型列。它存儲字節並且是可索引的。不幸的是它太小(2000字節)。 因此,我的答案在於將數據存儲在BLOB中,並通過兩個RAW類型的索引訪問它,因爲數據永遠不會超過4000字節。

索引看起來像這樣:

CREATE INDEX blob_to_raw_prd_ix 
ON product (product_id, 
      substr_dt(blob_summary,2000,1), 
      substr_dt(blob_summary,2000,2001)); 

其中

  • blob_summary是BLOB列i中的數據存儲在
  • substr_dt是用戶定義的確定性的函數(下面定義)

    CREATE OR REPLACE FUNCTION substr_dt(str BLOB,buffer_size int,offset int)RETURN RAW DETERMINISTIC是 BEGIN RETURN dbms_lob.substr(str,buffer_size,offset); END;

要訪問數據,我只需要使用別名查詢product_id和字段,例如,

SELECT  /*+ index(blob_to_raw_prd_ix) */ product_id, 
              substr_dt(blob_summary, 2000, 1) AS summary1, 
              substr_dt(blob_summary, 2000, 2001) AS summary2 
FROM  product 
WHERE  (product_id = ?); 

在這種情況下,summary_1表示第一2000個字節團塊,並總結2的最後2000個字節。 在兩個數組summary1和summary2上使用連接我得到blob的內容。

這與Jdbc一起工作,但我無法使它與Hibernate(還)一起工作。 這不是最好的解決方案,因爲數據在解釋之前需要重新處理。但是,它解決了數據訪問問題,無需編碼空間開銷。

1

您正在壓縮數據。壓縮的結果幾乎是總是二進制數據,而不是文本......我認爲這也是Snappy的情況。

要準確地存儲二進制數據作爲文本,你應該使用類似Base64的東西。你不要個字符 - 你有字節。

爲了有效地存儲壓縮文本,您應該將數據庫列更改爲面向二進制的類型,而不是面向文本的類型(基本上是BLOB而不是CLOB)。

0

有問題的char可能是oracle db的控制字符。在任何情況下,您可能都會考慮將數據保存爲「文本」或「clob」而不是varchar。

簡而言之,您可能需要在插入數據前使用zip或huffman類型的壓縮器。你玩過這樣的東西:How to compress a String in Java?

0

喬恩Skeet的答案是簡單地使用二進制字段,而不是文本字段是顯而易見的解決方案。

如果您確實需要使用文本字段,請先試驗一下,看看您可以在其中存儲什麼。我的猜測是,您可以存儲除零字節以外的任何字節,其中後者用於終止變長字符串。您可以簡單地將長度爲255的字符串與字節0x01..0xff一起存儲在其中,並檢索它以查看是否正確地返回了這些字節。如果你這樣做,那麼唯一要避免的字節就是零。

如果我的理論是正確的,那麼有幾種簡單的方法可以通過有限的數據擴展來擺脫零點。最簡單的是當你達到0時,發送一個0x80,0x01。當你得到一個0x80時,發送一個0x80,0x81。然後在解碼時,如果你看到一個0x80,只需得到下一個字節並減1即可。這將平均擴展數據流少於1%(0.78%)。

如果完全儘量減少擴展問題,您可以使用更復雜的編碼方案做得更好。

相關問題