1、hadoop中有一个WritableUtils.writeVLong方法,此方法对于long型数字进行一个编码以减少实际存储的数据长度。其编码方法如下:
* Serializes a long to a binary stream with zero-compressed encoding.
* For -112 <= i <= 127, only one byte is used with the actual value.
* For other values of i, the first byte value indicates whether the
* long is positive or negative, and the number of bytes that follow.
* If the first byte value v is between -113 and -120, the following long
* is positive, with number of bytes that follow are -(v+112).
* If the first byte value v is between -121 and -128, the following long
* is negative, with number of bytes that follow are -(v+120). Bytes are
* stored in the high-non-zero-byte-first order.
基本的原理是,如果需要写入的数据在-112到127之间的话,直接使用1个byte表示,剩余的16个能够使用一个byte表示的数分别作为后续byte数目长度的标志,因为要区分正负数,所以16个数分别表示整数的1-8byte长度,和负数的1-8byte的长度。
这种编码方式的有点是照顾了绝大多数能够使用一个byte编码的数字,最大的缺点是,两个byte所能编码的数字少了很多,并且两个byte以上长度的编码效率都下降了。
2、一种新的编码方式:
1)对于待编码的long型数字x,如果x是负数,取x=-x
2)确定编码所需bit数,(去掉高位的0直到最高位的bit值为1后的bite数目)
3)按照下表确定所需要的byte数目
(0是编码,s是符号位,xx..是实际的数据)
bit num byte num first byte code
0-6 1 0sxx xxxx
7-13 2 10sx xxxx
14-20 3 110s xxxx
21-27 4 1110 sxxx
28-34 5 1111 0sxx
35-41 6 1111 10sx
42-48 7 1111 110s
49-55 8 1111 1110
56-63 9 1111 1111
4)上表同时给出了第一个byte的编码方式,需要注意的是,当bytenum为8或者9的时候,第二个byte的第一个bit是符号位
3、比较两种编码方式,第二种编码在一个byte时的表达能力不如第一种,但是当需要编码的数据大于1个byte的时候,第二种编码方式都比第一种方法更加优秀,因此在实际的应用中可以根据实际数据的情况选择。
4、编码的目的是减少数据存储量,然后减少数据存储量的最好的方式是压缩,实际的压缩算法已经非常多,而且也已经发展的很成熟,如果需要的话,直接调用即可。
现在的一个问题是,对于一组long型的数值来说,直接存储为8个byte的long然后进行压缩,以及首先进行编码在压缩这两者有多大的差别呢?
经过一天的试验,证明了以下的结论:
1)如果你决定需要压缩了,那么一般来说编码已经不重要,编码所减少的冗余信息量,在压缩的过程中同样能够被消除掉
2)编码的应用场所主要在那些分块压缩的场合,里面需要写入一些元数据信息,如(块的长度等)这是使用编码的方式可以减少数据写入量。另外就是,很多情况下编码已经很大程度上消除了冗余信息,在不压缩的时候,使用编码的方法能在很多的程度上减少数据量,同时也避免了解压缩所需要的资源消耗(解码的代价要比解压的代价小的多)。