Java 在varchar列中存储snappy编码的数据

Java 在varchar列中存储snappy编码的数据,java,database,encoding,compression,varchar,Java,Database,Encoding,Compression,Varchar,我正在使用Snappy java对JSON数据进行编码,并希望将结果存储在数据库的varchar列中。 该数据库是采用ISO-8859-1编码的oracle数据库。 我在插入数据时遇到了编码问题。甲骨文似乎无法识别某些字符 我找到了一种解决方法,在插入压缩数据之前对其使用Base64编码。然后我可以很好地检索它:) 问题是Base64编码增加了我存储的数据的长度,从而减少了Snappy带来的节省 所以我的问题是:如果不在Base64中对数据进行编码,如何存储这些数据? 我希望使用varchar的

我正在使用Snappy java对JSON数据进行编码,并希望将结果存储在数据库的varchar列中。
该数据库是采用ISO-8859-1编码的oracle数据库。
我在插入数据时遇到了编码问题。甲骨文似乎无法识别某些字符

我找到了一种解决方法,在插入压缩数据之前对其使用Base64编码。然后我可以很好地检索它:)

问题是Base64编码增加了我存储的数据的长度,从而减少了Snappy带来的节省

所以我的问题是:如果不在Base64中对数据进行编码,如何存储这些数据? 我希望使用varchar的原因是,我希望能够使用oracle索引访问表,而不必访问表(性能绝对是个问题)

我也尝试过其他压缩算法,但它们似乎都有相同的问题。 我也看过yEnc,但找不到任何java编码器。此外,我不确定我是否理解yEnc列出的所有问题,因此我有点不愿意使用它


非常感谢你的帮助

您正在压缩数据。压缩的结果几乎总是二进制数据,而不是文本。。。我想Snappy也是这样

要准确地将二进制数据存储为文本,您应该使用Base64之类的东西。你没有字符-你有字节


为了有效地存储压缩文本,您应该将数据库列更改为面向二进制的类型,而不是面向文本的类型(基本上是BLOB而不是CLOB)。

所讨论的字符可能是oracle db的控制字符。在任何情况下,你都可以考虑将数据保存为“文本”或“Culb”,而不是VARCHAR。< /P>
除此之外,在插入数据之前,您可能需要为数据使用zip或huffman类型的压缩器。你玩过这样的游戏吗?

Jon Skeet的答案是简单地使用二进制字段而不是文本字段,这是显而易见的解决方案

如果你真的需要使用一个文本字段,那么首先尝试看看你能在其中存储什么。我的猜测是,您可以存储除零字节之外的任何字节,零字节用于终止可变长度字符串。您可以简单地存储一个长度为255的字符串,其中包含字节0x01..0xff,然后检索该字符串以查看是否准确地返回了这些字节。如果是这样,那么唯一要避免的字节就是零

若我的理论是正确的,那个么有几种简单的方法可以通过有限的数据扩展来消除零。最简单的方法是当你得到一个0时,发送一个0x80,0x01。当您得到一个0x80时,发送一个0x80,0x81。然后在解码时,如果你看到一个0x80,只需得到下一个字节并减去1。这将使河流平均扩展不到1%(0.78%)


如果绝对减少扩展问题,您可以使用更复杂的编码方案做得更好。

谢谢大家的帮助

我终于找到了解决办法。 因为我存储的是字节而不是字符,所以我将使用BLOB来存储数据。 BLOB的问题是它不能被索引。 另一种方法是使用原始类型列。它存储字节并可索引。不幸的是,它太小(2000字节)。 因此,在我的例子中,答案在于将数据存储在BLOB中,并通过两种原始类型的索引访问它,因为数据永远不会超过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列
  • substr_dt是一个用户定义的确定性函数(定义如下)

    创建或替换函数substr_dt(str BLOB,buffer_size int,offset int)返回原始值 确定性是 开始 返回dbms\u lob.substr(str,buffer\u size,offset); 结束

要访问数据,我只需要使用别名查询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表示blob的前2000个字节,summary 2表示最后2000个字节。 在两个数组summary1和summary2上使用串联,我得到blob的内容

这在Jdbc中是可以工作的,但是我还不能让它在Hibernate中工作。
这并不是最好的解决方案,因为数据在解释之前需要重新处理。但是,它在不增加编码空间开销的情况下解决了数据访问问题。

是否尝试为包含二进制数据的列编制索引?听起来你的设计好像有问题。您将不得不放弃压缩或索引。