当前位置: 首页 > 知识库问答 >
问题:

HBase行突变替换行的所有列

洪俊捷
2023-03-14

我有一个HBase(v0.94.7)表,其中只有一个列族,并且随着时间的推移,列会添加到表中。这些列以它们创建的时间戳命名,因此除非查询该行,否则我不知道它有哪些列。

现在给定一行,我想原子式地移除这个列族的所有现有列,并添加一组新的列和值。

所以我想到使用HBase的RowMutations:

RowMutations mutations = new RowMutations(row);

//delete the column family
Delete delete = new Delete(row);
delete.deleteFamily(cf);

//add new columns
Put put = new Put(row);
put.add(cf, col1, v1);
put.add(cf, col2, v2);

//delete column family and add new columns to same family
mutations.add(delete);
mutations.add(put);

table.mutateRow(mutations);

但这段代码最终只会删除列族,而不会添加新列。这种行为是意料之中的吗?

如果是这样,那么我如何实现我的目标,用一组新的列原子地替换列族的所有列呢?

下面是一个相同的测试用例:

import junit.framework.Assert;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableExistsException;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.NavigableMap;

public class TestHBaseRowMutations {
    static String tableName = "nnn";
    static byte[] cf1 = Bytes.toBytes("cf1");
    static byte[] row = Bytes.toBytes("r1");
    static HTablePool hTablePool;

    @BeforeClass
    public static void beforeClass() throws Exception {
        Configuration config = HBaseConfiguration.create();
        hTablePool = new HTablePool(config, Integer.MAX_VALUE);
        HBaseAdmin admin = new HBaseAdmin(config);
        HTableDescriptor tableDescriptor = new HTableDescriptor(tableName);
        tableDescriptor.addFamily(new HColumnDescriptor(cf1));
        try {
            admin.createTable(tableDescriptor);
        } catch (TableExistsException ignored){}
    }

    @Before
    public void before() throws Exception {
        HTableInterface table = hTablePool.getTable(tableName);
        try {
            Delete delete = new Delete(row);
            table.delete(delete);
            System.out.println("deleted old row");

            Put put = new Put(row);
            put.add(cf1, Bytes.toBytes("c1"), Bytes.toBytes("v1"));
            put.add(cf1, Bytes.toBytes("c11"), Bytes.toBytes("v11"));
            table.put(put);
            System.out.println("Created row with seed data");
        } finally {
            table.close();
        }
    }


    @Test
    public void testColumnFamilyDeleteRM() throws Exception {
        HTableInterface table = hTablePool.getTable(tableName);
        try {
            RowMutations rm =new RowMutations(row);

            //delete column family cf1
            Delete delete = new Delete(row);
            delete.deleteFamily(cf1);
            rm.add(delete);
            System.out.println("Added delete of cf1 column family to row mutation");

            //add new columns to same column family cf1
            Put put = new Put(row);
            put.add(cf1, Bytes.toBytes("c1"), Bytes.toBytes("new_v1"));
            put.add(cf1, Bytes.toBytes("c11"), Bytes.toBytes("new_v11"));
            rm.add(put);
            System.out.println("Added puts of cf1 column family to row mutation");

            //atomic mutate the row
            table.mutateRow(rm);
            System.out.println("Mutated row");

            //now read the column family cf1 back
            Result result = table.get(new Get(row));
            NavigableMap<byte[], byte[]> familyMap = result.getFamilyMap(cf1);

            //column family cf1 should have 2 columns because of the Put above
            //------Following assert fails as cf1 does not exist anymore, why does cf1 not exist anymore?-------
            Assert.assertNotNull(familyMap);
            Assert.assertEquals(2, familyMap.size());
        } finally {
            table.close();
        }
    }
}

共有1个答案

岳曦
2023-03-14

在HBase用户论坛上发布了同样的问题,结果发现这是HBase的一个bug。

预期的行为是,如果RowMutation对某个column-family/column/row有一个Delete,然后对同一个column-family/column/row有一个Put,那么也应该遵守Put(但目前不是这样)。

HBase用户组对此的讨论:http://apache-hbase.679495.n3.nabble.com/using-rowmutations-to-replace-all-columns-of-a-row-td4045247.html

同样的HBase JIRA:https://issues.apache.org/JIRA/browse/HBase-8626,它也提供补丁。

 类似资料:
  • 如何替换所有标签

  • 问题内容: 由于DOM突变被w3c标记为已弃用,因此存在一种(快速)替代方法来检测属性修改在DOM中? 问题答案: 据我所知,还没有其他选择,因此您只能使用Firefox和Opera支持的方法。在IE中,您有活动,但是无法在Chrome / Safari中获得类似的功能。根据您要完成的任务和目标浏览器,您可以做很多事情: 为要监视的属性定义获取器和设置器 重写方法一样,… 我本人一直在从事跨浏览器

  • 我正在尝试使用JOLT转换https://jolt-demo.appspot.com/. 我想将所有“大师”值替换为“7.11”。 输入: 期望输出: 我似乎无法在不更改/更改数据结构的情况下进行转换或转换。当前方法: 电流输出:

  • 昨天我正在处理定制的信件和备忘录。我做了映射关键字,例如:[出生日期],[电子邮件],[员工],[薪水]等,这些关键字将在生成时被替换。 例:尊敬的[员工],您目前的工资是[薪水]。 预期产量: 输出:亲爱的约翰,你现在的薪水是12000。 我使用的是方法这里是一个代码。 但问题是: 我很困惑,谷歌它并试图使它正确,之后我用 现在它运行良好。问题是为什么replace all会有这样的行为,的核心

  • 问题内容: 是否可以使用相同的值替换格式化字符串中的所有变量? 就像是: 会回来的 问题答案: 有可能,但是必须修改格式字符串,必须使用 显式参数索引 : 显式参数索引: 在Printf,Sprintf和Fprintf中,默认行为是为每个格式化动词格式化在调用中传递的连续参数。但是,动词前的符号[n]表示第n个单索引参数将被格式化。宽度或精度的’*’之前的相同符号选择保存该值的参数索引。在处理了带

  • 如何用updateNum变量替换price的值(存储在number变量中)。 如果我在价格值下面的代码没有更新之后打印数据框架,但是如果我打印updateNum变量,它将显示正确更新的变量。