0

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

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

问题在于 Base64 编码增加了我随后存储的数据的长度,从而减少了使用 Snappy 获得的节省......

所以我的问题是:如何在不使用 Base64 编码的情况下存储这些数据?我想使用 varchar 的原因是因为我希望能够使用 oracle 索引访问表而无需访问表(性能绝对是一个问题)。

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

非常感谢您的帮助!

4

4 回答 4

1

您正在压缩数据。压缩的结果几乎总是二进制数据,而不是文本......我认为 Snappy 也是如此。

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

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

于 2012-07-27T14:24:49.623 回答
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 列
  • substr_dt 是用户定义的确定性函数(定义如下)

    创建或替换函数 substr_dt(str BLOB, buffer_size int, offset int) RETURN RAW DETERMINISTIC IS BEGIN RETURN dbms_lob.substr(str,buffer_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(还)。这不是最好的解决方案,因为数据在被解释之前需要重新处理。但是,它在没有编码空间开销的情况下解决了数据访问问题。

于 2012-08-02T14:18:03.280 回答
0

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

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

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

如果绝对最小化扩展很重要,您可以使用更复杂的编码方案做得更好。

于 2012-07-27T15:14:30.820 回答
0

有问题的字符可能是 Oracle 数据库的控制字符。在任何情况下,您都可能需要考虑将数据保存为“文本”或“clob”而不是 varchar。

除此之外,您可能需要在插入数据之前对数据使用 zip 或 huffman 类型的压缩器。你玩过这样的东西:如何在 Java 中压缩字符串??

于 2012-07-27T14:24:57.267 回答