hbase - 读写方式API, get、 scan、Filter模糊查询以及分页

一、创建表

   //创建表 
         try {
            Admin admin = conn.getAdmin();
            TableName tableName = TableName.valueOf("user_fengze");
        if (admin.tableExists(tableName)) {// 如果存在要创建的表,那么先删除,再创建
            admin.disableTable(tableName);
            admin.deleteTable(tableName);
            System.out.println(tableName + " is exist,detele....");
            }
            HTableDescriptor tableDescriptor = new HTableDescriptor(tableName);
            tableDescriptor.addFamily(new HColumnDescriptor("columnfamily1"));
            tableDescriptor.addFamily(new HColumnDescriptor("columnfamily2"));
            admin.createTable(tableDescriptor);

二、增 数据

//增 改:put来覆盖
// 插入一条数据        
Put put = new Put(Bytes.toBytes(rowkey), ts);
        put.addColumn(Bytes.toBytes(family), Bytes.toBytes(column), Bytes.toBytes(value)); 
        htable.put(put);

      // 插入多条数据
        Table table = conn.getTable(TableName.valueOf("tableName001"));

        // 构造要插入的数据为一个Put类型(一个put对象只能对应一个rowkey)的对象
        Put put = new Put(Bytes.toBytes("rowkey001"));
        put.addColumn(Bytes.toBytes("columnfamily1"), Bytes.toBytes("username"), Bytes.toBytes("张三"));
        put.addColumn(Bytes.toBytes("columnfamily1"), Bytes.toBytes("age"), Bytes.toBytes("18"));
        put.addColumn(Bytes.toBytes("columnfamily1"), Bytes.toBytes("addr"), Bytes.toBytes("北京"));
        //addColumn(byte[] family, byte[] qualifier, byte[] value)
        Put put2 = new Put(Bytes.toBytes("rowkey002"));
        put2.addColumn(Bytes.toBytes("columnfamily2"), Bytes.toBytes("username"), Bytes.toBytes("李四"));
        put2.addColumn(Bytes.toBytes("columnfamily2"), Bytes.toBytes("age"), Bytes.toBytes("28"));
        put2.addColumn(Bytes.toBytes("columnfamily2"), Bytes.toBytes("name"), Bytes.toBytes("上海"));
 
        ArrayList<Put> puts = new ArrayList<>();
        puts.add(put);
        puts.add(put2);
 
        // 插进去
        table.put(puts);

        table.close();
        conn.close(); 

      //循环插入大量数据
       Table table = conn.getTable(TableName.valueOf("user_table"));
        ArrayList<Put> puts = new ArrayList<>();
        for (int i = 0; i <100; i++) {
        Put put = new Put(Bytes.toBytes("rowkey"+i));
        put.addColumn(Bytes.toBytes("columnfamily1"),Bytes.toBytes("name"),Bytes.toBytes("zhangsan"+i));
        put.addColumn(Bytes.toBytes("columnfamily1"),Bytes.toBytes("age"),Bytes.toBytes("18"+i));
        puts.add(put);
        }
        table.put(puts);
        table.close();
        conn.close(); 

三、删除数据

  Table table = conn.getTable(TableName.valueOf("user_table"));
        // 构造一个对象封装要删除的数据信息
        Delete delete1 = new Delete(Bytes.toBytes("rowkey001"));
        Delete delete2 = new Delete(Bytes.toBytes("rowkey002"));
        //删除name列
        delete2.addColumn(Bytes.toBytes("columnfamily1"),Bytes.toBytes("name"));
        
        ArrayList<Delete> arrayList = new ArrayList();
        arrayList.add(delete1);
        arrayList.add(delete2);
        
        table.delete(arrayList);
        
        table.close();
        conn.close(); 

二、HBase的查询实现只提供两种方式:

1、按指定RowKey获取唯一一条记录,get方法(org.apache.hadoop.hbase.client.Get)

Get 的方法处理分两种 : 设置了 ClosestRowBefore 和没有设置的 rowlock .主要是用来保证行的事务性,即每个 get 是以一个 row 来标记的.一个 row 中可以有很多 family 和 column.

2、按指定的条件获取一批记录,scan方法(org.apache.hadoop.hbase.client.Scan)

https://www.cnblogs.com/liupengpengg/p/9197157.html

实现条件查询功能使用的就是scan方式,scan在使用时有以下几点值得注意:

1、scan可以通过setCaching与setBatch方法提高速度(以空间换时间);

2、scan可以通过setStartRow与setEndRow来限定范围。范围越小,性能越高。

通过巧妙的RowKey设计使我们批量获取记录集合中的元素挨在一起(应该在同一个Region下),可以在遍历结果时获得很好的性能。

3、scan可以通过setFilter方法添加过滤器,这也是分页、多条件查询的基础。

3.全表扫描,即直接扫描整张表中所有行记录 

Get:

    HTable table = new HTable(hbaseConf, "table001");
    Get get = new Get(Bytes.toBytes("row01"));
    get.addFamily(Bytes.toBytes("colfamily01"));//也可不加
    Result result = table.get(get);

    // 从结果中取用户指定的某个key的value
    byte[] value = result.getValue(Bytes.toBytes("colfamily01"), Bytes.toBytes("col02"));
    System.out.println(" 查询结果:" + Bytes.toString(value)); 
    System.out.println(new String(value)); 

     
   for(KeyValue kv:result.raw()){
    System.out.println("KeyValue---"+kv);
    System.out.println("row=>"+new String(kv.getRow()));
    System.out.println("family=>"+new String(kv.getFamily(),"utf-8")+": "+new String(kv.getValue(),"utf-8"));
    System.out.println("qualifier=>"+new String(kv.getQualifier())+"\n");
   }

    // 遍历整行结果中的所有kv单元格
    CellScanner cellScanner = result.cellScanner();
    while (cellScanner.advance()){
    Cell cell = cellScanner.current();

    byte[] rowArray = cell.getRowArray(); //本kv所属的行键的字节数组
    byte[] familyArray = cell.getFamilyArray(); //列族名的字节数组
    byte[] qualifierArray = cell.getQualifierArray();//列名的字节数据
    byte[] valueArray = cell.getValueArray();// value的字节数组

    System.out.println("行键:"+new String(rowArray,cell.getRowOffset(),cell.getRowLength()));
    System.out.println("列族:"+new String(familyArray,cell.getFamilyOffset(),cell.getFamilyLength()));
    System.out.println("列名:"+new String(qualifierArray,cell.getQualifierOffset(),cell.getQualifierLength()));
    System.out.println("value:"+new String(valueArray,cell.getValueOffset(),cell.getValueLength()));

    table.close();
    conn.close(); 


//批量查询rowkry
 List<Get> gets = new ArrayList<Get>();
        if (get != null) {
            gets.add(get);
           }
  Result[] rss = table.get(gets);

 for (Result rs : rss) {
         List<HBaseRecord> recordList = this.getResult(rs);
         String rowKey = Bytes.toString(rs.getRow());
         recordsMap.put(rowKey, recordList);
            }

Scan:

Table table = connection.getTable(TableName.valueOf("table3"));
    Scan scan = new Scan();
    //过滤器 某一列的范围 :13<age<18  
    Filter filter1 = new SingleColumnValueFilter("cf".getBytes(), "age".getBytes(), CompareFilter.CompareOp.GREATER_OR_EQUAL, "13".getBytes());
    Filter filter2 = new SingleColumnValueFilter("cf".getBytes(), "age".getBytes(), CompareFilter.CompareOp.LESS_OR_EQUAL, "18".getBytes());
    FilterList filterList = new FilterList();
    filterList.addFilter(filter1);
    filterList.addFilter(filter2);
    scan.setFilter(filterList);
    //扫某一列name列 addColumn(byte[] family, byte[] qualifier) 
    //scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"));
    //行键过滤器
    scan.setStartRow(Bytes.toBytes("00001"));
    scan.setStopRow(Bytes.toBytes("00009"));
    

   scanRow.addColumn(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol02"))
          .addColumn(Bytes.toBytes("xcolfam01"), Bytes.toBytes("xcol04"))
          .setStartRow(Bytes.toBytes("xrow03"))
          .setStopRow(Bytes.toBytes("xrow05"));


    ResultScanner resultScanner = table.getScanner(scan);
    for (Result result : resultScanner) {
          //getValue(byte[] family, byte[] qualifier)
        String name = new String(result.getValue("cf".getBytes(), "name".getBytes()));
        int age = Integer.valueOf(new String(result.getValue("cf".getBytes(), "age".getBytes())));
        String rowKey = new String(result.getRow());
        System.out.println(rowKey + "\t" + "cf:name-->" + name + ", cf:age-->" + age);
    }


假设test表中存储着如下RowKey: 
//12Aabb 
//3aabb 
//Aabb 
//aabb
结果:
//12Aabb
//3aabb 

 

三、Filter   

代码参考https://www.cnblogs.com/similarface/p/5805973.html

scan "table_name" ,{FILTER=>”PrefixFilter(‘1’) AND ValueFilter(=,’substring:2015’)”, STARTROW=>’2’,ENDROW=>’3’, LIMIT=>10} 

一般不建议用Filter,scan.setFilters(),通过filter设置的条件查不到数据时,响应速度非常慢,大概在十几秒,有时会超时


有两个参数类在各类Filter中经常出现,统一介绍下:

(1)比较运算符 CompareFilter.CompareOp
比较运算符用于定义比较关系,可以有以下几类值供选择:
EQUAL                相等
GREATER              大于
GREATER_OR_EQUAL     大于等于
LESS                 小于
LESS_OR_EQUAL        小于等于
NOT_EQUAL            不等于

(2)比较器  ByteArrayComparable
通过比较器可以实现多样化目标匹配效果,比较器有以下子类可以使用:
BinaryComparator           匹配完整字节数组 
BinaryPrefixComparator     匹配字节数组前缀 
BitComparator              
RegexStringComparator      正则表达式匹配
SubstringComparator        子串匹配

 

HBASE用到的几个filter

1,FilterList
FilterList 代表一个过滤器链,它可以包含一组即将应用于目标数据集的过滤器,过滤器间有 
“与” FilterList.Operator.MUST_PASS_ALL  
“或” FilterList.Operator.MUST_PASS_ONE  的关系。

    FilterList list = new FilterList(FilterList.Operator.MUST_PASS_ONE);   //数据只要满足一组过滤器中的一个就可以
    SingleColumnValueFilter filter1 = new SingleColumnValueFilter(cf,column,CompareOp.EQUAL,Bytes.toBytes("my value"));
    list.add(filter1);
    SingleColumnValueFilter filter2 = new SingleColumnValueFilter(cf,column,CompareOp.EQUAL,Bytes.toBytes("my other value"));
    list.add(filter2);
    Scan scan = new Scan();
    scan.setFilter(list); 
  • 行键过滤器 RowFilter

Filter filter1 = new RowFilter(CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes(“row-22”)));
scan.setFilter(filter1);

  • 列族过滤器 FamilyFilter

Filter filter1 = new FamilyFilter(CompareFilter.CompareOp.LESS, new BinaryComparator(Bytes.toBytes(“colfam3”)));
scan.setFilter(filter1);

  • 列过滤器 QualifierFilter

Filter filter = new QualifierFilter(CompareFilter.CompareOp.LESS_OR_EQUAL, new BinaryComparator(Bytes.toBytes(“col-2”)));

  • 值过滤器 ValueFilter

Filter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(".4") );

 

SingleColumnValueFilter -列值过滤器,指定列值,还可以正则表达式查询方法                                                 

过滤某列值大于多少小于多少:  

  List<Filter> filters = new ArrayList<Filter>();                        
             filters.add(  new SingleColumnValueFilter(Bytes.toBytes("cfinfo"),  //列族
                          Bytes.toBytes("column"),  //列名                                 
                          CompareOp.GREATER,Bytes.toBytes("1359901"]) ) //值     
             FilterList filterList1 = new FilterList(Operator.MUST_PASS_ALL,filters);                                                               
             sn.setFilter(filterList1);    

ValueFilter:                                                                          

不需要指定某个列,含指某个值的列的数据都取出来,混在一起

HTable table = new HTable(config, tableName);                                         
    Scan scan = new Scan();                                                                      
    System.out.println("只列出值包含data1的列");                                      
    Filter filter1 = new ValueFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator("data1"));                                            
 scan.setFilter(filter1);         

RowFilter                                                                             
Rowkey中包括某些字符串,字符串存在list a内  

提取rowkey以01结尾数据
Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL,new RegexStringComparator(".*01$"));

提取rowkey以包含201407的数据
Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL,new SubstringComparator("201407"));

提取rowkey以123开头的数据
Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL,new BinaryPrefixComparator("123".getBytes()));     


 for (int a=0;a<size;a++){                                                                         
   //    Filter filter2 = new RowFilter(CompareOp.EQUAL,  new RegexStringComparator(".*"+maclist.get(a)+"$"));                 
         Filter filter2 = new RowFilter(CompareOp.EQUAL,  new SubstringComparator(maclist.get(a)));                     
         filters.add(filter2);                                                     
         }                                                                         
     FilterList filterList1 = new FilterList(Operator.MUST_PASS_ONE,filters);  
     sn.setFilter(filterList1);      

PageFilter 和 StartRow 配合使用,指定页面行数,返回对应行数的结果集。

需要注意的是,该过滤器并不能保证返回的结果行数小于等于指定的页面行数,因为过滤器是分别作用到各个region server的,它只能保证当前region返回的结果行数不超过指定页面行数。

(但这种方法效率比较低,且有冗余查询)

Table table = connection.getTable(TableName.valueOf("user"));
        PageFilter pf = new PageFilter(2L);
        Scan scan = new Scan();
        scan.setFilter(pf);
        scan.setStartRow(Bytes.toBytes("zhangsan_"));
        ResultScanner rs = table.getScanner(scan);
 
返回的结果实际上有四条,因为这数据来自不同RegionServer, 
[row:zhangsan_1495527850759],[family:account],[qualifier:idcard],[value:9897645464646],[time:1495556648664]
[row:zhangsan_1495527850759],[family:account],[qualifier:passport],[value:5689879898],[time:1495636370056]
[row:zhangsan_1495527850824],[family:account],[qualifier:country],[value:china],[time:1495636452285]
[row:zhangsan_1495527850824],[family:account],[qualifier:name],[value:zhangsan],[time:1495556648729]
 
  /**
     * 获取指定Rowkey正则的资讯列表(分页)
     *
     * @param pageSize   页大小
     * @param lastRowKey 上一页最后的rowkey
     * @param rowkeyReg  Rowkey正则
     * @return 资讯列表
     */
    public List<GeneralNewsInfo> getData(int pageSize, String lastRowKey, String rowkeyReg) {
        List<GeneralNewsInfo> dataList = new ArrayList<>();
        getConnection();
        try {
            // 二级索引表查询索引数据
            Table table = conn.getTable(TableName.valueOf(RcmdHbaseConstants.RCMD_NEWS_TITLE_INDEX));
            Scan scan = new Scan();
            // 构建模糊查询的Filter和分页的Filter
            FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
            if (rowkeyReg != null) {
                RegexStringComparator regex = new RegexStringComparator(rowkeyReg);
                Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, regex);
                filterList.addFilter(filter);
            }
            Filter pageFilter = new PageFilter(pageSize);
            Filter rowFilter = new RowFilter(CompareFilter.CompareOp.GREATER,
                    new BinaryComparator(Bytes.toBytes(lastRowKey)));
            filterList.addFilter(pageFilter);
            filterList.addFilter(rowFilter);
            scan.setFilter(filterList);
            ResultScanner rs = table.getScanner(scan);
            Result result;
            int rowNum = 0;
            while ((result = rs.next()) != null) {
                if (rowNum >= pageSize) {
                    break;
                }
                List<Cell> listCells = result.listCells();
                for (Cell cell : listCells) {
                    String rowkey = Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                    // 索引拿到rowkey 去元数据表中获取元数据
 

 

由于其原生带有PrefixFilter这种对ROWKEY的前缀过滤查询,因此想着实现的后缀查询的过程中,发现这一方面相对来说还是空白。

因此,只能采用一些策略来实现,主要还是采用正则表达式的方式。

 

Filter filter2 = new RowFilter(CompareFilter.CompareOp.EQUAL,  new RegexStringComparator(".*_2015100112"));
// co RowFilterExample-2-Filter2 Another filter, this time using a regular expression to match the row keys.
           scan.setFilter(filter2);
           ResultScanner scanner2 = table.getScanner(scan);
           // ^^ RowFilterExample
           System.out.println("Scanning table #2...");
           // vv RowFilterExample
           for (Result res : scanner2) {
             System.out.println(res);
           } 

 

  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: HBase-Java API 是一种用于管理 HBase 表的编程接口。使用 HBase-Java API,开发人员可以编写 Java 代码来创建、删除、修改和查询 HBase 表。HBase-Java API 提供了一系列类和方法,可以让开发人员轻松地与 HBase 表进行交互。例如,可以使用 HBaseAdmin 类来管理 HBase 表,使用 HTable 类来访问 HBase 表中的数据,使用 Put 类来插入数据,使用 Get 类来获取数据,等等。总之,HBase-Java APIHBase 的重要组成部分,它为开发人员提供了强大的工具来管理和操作 HBase 表。 ### 回答2: HBase是一个分布式的列式存储数据库,在很多大数据应用中得到广泛的使用。它采用Hadoop作为其底层基础框架,同时提供了Java API供开发人员使用HBase的Java API为开发人员提供了一个管理表的接口,使得开发人员可以对HBase数据库中的表进行创建、读取、修改和删除等基本操作。 首先,我们需要用Java API创建一个HBase数据库中的表。使用HBase的Java API创建表的流程如下: 1. 首先需要获取HBase Configuration对象,并设置HBase连接参数以连接HBase数据库。 2. 接下来,需要获取HBase Admin对象,以便在操作HBase数据库表之前检查表是否存在,如果表不存在,需要创建该表。 3. 通过HBase的Java API创建表时,需要指定表的表名、列族的名称以及版本数等属性。 4. 创建表时需要考虑表的region的分配问题,可以对表的region进行手动或自动分片,以此来控制HBase的负载均衡。 创建了HBase数据库中的表之后,我们可以使用Java API对表进行读写操作。在进行读写操作时,需要使用HBase的Java API提供的Get的方法来获取表中的数据、Scan方法来扫描整个表、以及Put方法来向表中插入数据。此外,在进行表操作时还需要设置一些常见的数据操作参数,例如版本数、时间戳等。 在使用HBase的Java API时,还需要注意一些性能优化的问题,例如何时启用缓存、何时触发分区策略以及如何优化HBase表的大小等。这些优化措施能够在HBase的性能以及数据读写时的延迟方面提供很好的支持和帮助。 总的来说,HBase的Java API提供的表管理接口为开发人员提供了非常方便和快捷的方式操作HBase数据库中的表。通过使用这些API,开发人员可以创建、读取、修改和删除表的数据,并且能够充分应用HBase的分布式特性来优化数据管理和性能提升。 ### 回答3: HBase是一个开源、分布式、非关系型数据库,它可以存储和处理大规模结构化、半结构化和非结构化数据。HBase Java APIHBase的官方API,它提供了对HBase表的管理和操作功能,让开发人员可以通过Java代码轻松地连接到HBase数据库。 在使用HBase Java API管理表时,首先需要创建一个HBaseConfiguration对象,它包含了连接HBase数据库所需的配置信息,如Zookeeper地址、HBase根目录等。然后,可以使用HBaseAdmin类创建、删除、修改表,以及列族等操作。例如,创建一个表可以通过以下代码实现: ``` HBaseAdmin admin = new HBaseAdmin(HBaseConfiguration.create()); HTableDescriptor tableDescriptor = new HTableDescriptor("table_name"); HColumnDescriptor columnDescriptor = new HColumnDescriptor("column_family"); tableDescriptor.addFamily(columnDescriptor); admin.createTable(tableDescriptor); ``` 创建表时,需要先通过HTableDescriptor类定义表名称,然后通过HColumnDescriptor类定义列族名称。可以通过addFamily()方法将列族添加到表描述中,最后通过HBaseAdmin的createTable()方法创建表。 除了创建表之外,HBase Java API还提供了许多其他的操作,如获取表信息、获取所有表的列表、删除表等。同时,HBase Java API还提供了对数据的CRUD操作,包括put、get、scan、delete等方法,让开发人员可以方便地进行数据操作。 总之,HBase Java API是一个非常强大的工具,它可以使开发人员轻松地管理HBase数据库,并实现数据的高效存储和处理。但是,在使用HBase Java API时,需要了解HBase的基本知识和API的用法,才能更好地发挥其功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四月天03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值