【问题标题】:Phoenix doesn't display negative integer values correctlyPhoenix 无法正确显示负整数值
【发布时间】:2016-07-07 23:09:32
【问题描述】:

我正在创建一个值为整数 -17678 的 HBASE 表。但是当我从凤凰取回它时,它给了我一个不同的积极价值。 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();
          }

    }
}

凤凰检索:

从 TEST 中选择 CAST("Value" AS INTEGER) ;

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

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

【问题讨论】:

    标签: java hadoop serialization hbase phoenix


    【解决方案1】:

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

    二进制表示是一个符号位翻转的 4 字节整数(因此负值排在正值之前)。

    所以要从 HBase 序列化格式转换为 Phoenix 格式:

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

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

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

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

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


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

    对于整数,您可能希望使用位掩码对您的i 进行异或运算以翻转符号位。

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

    (10000000000000000000000000000000)2 = (-2147483648)10
    

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

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

    【讨论】:

    • 谢谢。那么当我使用 JDBC 驱动程序查询时,我会得到正确的值吗?我不想使用 phoenix 插入数据,hbase 客户端 API 是最好的选择。
    • 它不会按原样工作,因为数据没有按照 Phoenix 预期的格式序列化。我用一个关于如何使用 HBase 插入可以被 Phoenix 正确反序列化的数据的示例更新了我的答案。
    • 所以唯一的解决方法是使用 pheonix 本身插入数据?
    • 我使用 HBase 使用解决方法编辑了我的原始答案。此解决方案对您有用吗?
    • 基本上你会想要在addColumn 中用i ^ -2147483648 替换Bytes.toBytes(i)。 -2147483648 是当您与整数进行异或时将翻转符号位的位掩码,并且您需要为每个有符号数据类型使用不同的位掩码。
    【解决方案2】:

    尝试类似:

    //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));
    

    【讨论】:

      猜你喜欢
      • 2013-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-28
      • 2015-04-08
      • 1970-01-01
      • 2010-10-10
      • 1970-01-01
      相关资源
      最近更新 更多