Phoenix 无法正确显示负整数值

Phoenix doesn't display negative integer values correctly

我正在创建一个值为 -17678 的 HBASE table。但是当我从 pheonix 取回它时,它给了我不同的正值。 RowKey是复合rowkey,rowkey没有问题

Hbase 插入:

public class test
{
public static void main(String args[])
{
        Configuration config = HBaseConfiguration.create();

          Connection connection = ConnectionFactory.createConnection(config);
          Table table = connection.getTable(TableName.valueOf("TEST"));
          Integer i=-17678;

          try
          {
          Put p = new Put(Bytes.toBytes("rowkey"));
          p.addColumn(Bytes.toBytes("test"),Bytes.toBytes("test"),Bytes.toBytes(i));
          table.put(p);
          }
          finally
          {
             table.close();
             connection.close();
          }

    }
}

凤凰检索:

select CAST("Value" AS INTEGER) 来自 TEST ;

+------------------------------------------+
|         TO_INTEGER(test."Value")         | 
+------------------------------------------+
| 2147465970                               | 
+------------------------------------------+

这里有什么问题吗?还是凤凰问题?

http://phoenix.apache.org/language/datatypes.html

The binary representation is a 4 byte integer with the sign bit flipped (so that negative values sorts before positive values).

因此要从 HBase 序列化格式转换为 Phoenix 格式:

(-17678)10 = (11111111111111111011101011110010)2
=> (01111111111111111011101011110010)2 = (2147465970)10

因此输出符合预期。使用 HBase 插入数据时,您需要注意二进制表示。

只有 CHAR 和 UNSIGNED_* 数据类型才能将 HBase toByte 直接读取到 Phoenix。您必须为其他数据类型适当地序列化。 IE。当您想插入 -17678 时设置 i = 2147465970

我推荐使用Phoenix 来插入数据。如果您担心让您的应用程序依赖于依赖项,Phoenix 提供了一个 "thin" jdbc 驱动程序(4mb 而不是 86mb)。

https://phoenix.apache.org/server.html


如果您绝对必须使用 HBase,则可以使用按位异或来序列化有符号数。

对于整数,您需要使用位掩码对 i 进行异或运算以翻转符号位。

应用于 4 字节整数的位掩码是:

(10000000000000000000000000000000)2 = (-2147483648)10

http://ideone.com/anhgs5 ,我们得到 2147465970。如果您使用 HBase 插入它,当您使用 Phoenix 读取时,您将读取 -17678).

Bigint(与日期时间类型共享位掩码)、Smallint、Float 和 Double 需要不同的位掩码。

试试这样的东西:

//Add dependencies in your pom.xml
<dependency>
            <groupId>org.apache.phoenix</groupId>
            <artifactId>phoenix-core</artifactId>
            <version>${phoenix.core.version}</version>
            <scope>provided</scope>
</dependency>

比:

//Import these classes. More types available
import org.apache.phoenix.schema.types.{PDecimal, PInteger, PVarchar}
//and replace your addColumn method by this one:
p.addColumn(Bytes.toBytes("test"),Bytes.toBytes("test"),PInteger.INSTANCE.toBytes(i));
//Or if you wish a Decimal
p.addColumn(Bytes.toBytes("test"),Bytes.toBytes("test"),PDecimal.INSTANCE.toBytes(i));