Hbase的scan方法

Apache HBase是一种开源、分布式、版本控制的非关系型数据库系统,类似于Google的Bigtable。HBase提供了几种用于检索数据的API,其中包括scan()和get()方法。

Scan()方法是用于扫描表中的多个行的API。它可以用于从一个或多个范围内获取多行数据,以及使用过滤器来进行数据过滤和排序。Scan操作是无阻塞性的,因此它适用于大多数查询场景。通过设置缓存大小和批处理大小等参数,可以优化扫描性能。 Scan方法支持以下几种参数:

Start Row:起始行
Stop Row:终止行
Time Range:时间范围(可选)
Column Family:列族(可选)
Columns:列限制列表(必需)

使用 Scan 方法时,必须指定要检索的列。如果未指定列,则将返回所有列。Scan 方法返回一个 ResultScanner 对象,该对象包含了从 HBase 表检索到的 Result 对象列表。Result 代表单个行的结果,并包含了该行的详细信息,包括行键和列值。

以下是一个示例代码段,说明如何使用Java API进行Scan操作:

Configuration config = HBaseConfiguration.create();
HTable table = new HTable(config, "table-name");
Scan scan = new Scan();

//设置开始行和结束行
scan.setStartRow(Bytes.toBytes("start-row"));
scan.setStopRow(Bytes.toBytes("stop-row"));

//添加返回列
scan.addColumn(Bytes.toBytes("column-family"), Bytes.toBytes("column-qualifier"));

ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
    //遍历结果并进行处理
}

scanner.close();
table.close();

在这个示例中,首先创建了一个 Configuration 对象作为 HBase 连接参数,然后创建了一个 HTable 对象来表示要扫描的表。然后,我们使用Scan实例设置起始行和终止行,并添加了要返回的列。最后我们通过遍历ResultScanner来检索结果,并完成必要的处理。

需要注意的是, Scan 方法是基于列族和列名称来检索数据的,而不是基于列值。对于基于列值的检索,可以使用HBase中的 Filter。

Hbase的get方法

Get()方法用于检索单个行。它接受一个RowKey作为参数,并检索对应的行。当需要检索特定行时,使用get()方法会比scan()方法更有效率。Get()操作不支持服务器端过滤器,并且只返回单个行,因此它很快并且适合于根据RowKey查找记录。

HBase的Get方法是一种基于行键的检索数据的操作,它通过读取单个行来获取特定的列族、列限定符和时间戳信息。Get操作是用于读取单个行数据的最基本的API之一。
使用HBase的Get方法时,必须指定要检索的行键,可以通过检索指定的列族或限定符进一步规定检索范围,还可以设置时间戳以返回特定时间范围的值。Get方法返回一个Result对象,其中包含了从HBase表中检索到的行的详细信息。
以下是一个示例代码段,说明如何使用Java API进行Get操作:

Configuration config = HBaseConfiguration.create();
HTable table = new HTable(config, "table-name");
Get get = new Get(Bytes.toBytes("row-key"));

//添加返回的列族和列限定符
get.addColumn(Bytes.toBytes("column-family"), Bytes.toBytes("column-qualifier"));

//指定最大版本数和时间戳范围
get.setMaxVersions(5);
get.setTimeRange(startTimeStamp, endTimeStamp);

Result result = table.get(get);

在这个示例中,我们首先创建了一个 Configuration 对象作为 HBase 连接参数,然后创建了一个 HTable 对象来表示要扫描的表。我们通过Get方法指定了要检索的行键和要返回的列族和列限定符,并指定了可选的最大版本数和时间戳范围。最后我们通过调用table.get(get)方法获取特定行数据的Result对象。

需要注意的是, HBase的Get方法只能用于读取单个行数据,如果需要获取多个行或者进行范围查询,需要使用HBase中的Scan方法。

使用案例

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellScanner;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;

public class HBaseDemo {

    private static Configuration conf = null;
    private static Connection conn = null;

    static {
        conf = HBaseConfiguration.create();
        // 配置Zookeeper地址
        conf.set("hbase.zookeeper.quorum", "localhost:2181");
        try {
            conn = ConnectionFactory.createConnection(conf);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        // 获取要操作的表名
        TableName tableName = TableName.valueOf("testTable");

        // 1. 获取表对象
        Table table = conn.getTable(tableName);

        // 2. 单行检索
        Get get = new Get(Bytes.toBytes("row1"));
        Result result = table.get(get);
        CellScanner cellScanner = result.cellScanner();
        while (cellScanner.advance()) {
            Cell currentCell = cellScanner.current();
            // 获取列族名称
            byte[] family = currentCell.getFamilyArray();
            int familyOffset = currentCell.getFamilyOffset();
            int familyLength = currentCell.getFamilyLength();
            String columnFamily = Bytes.toString(family, familyOffset, familyLength);
            // 获取列名称
            byte[] qualifier = currentCell.getQualifierArray();
            int qualifierOffset = currentCell.getQualifierOffset();
            int qualifierLength = currentCell.getQualifierLength();
            String columnName = Bytes.toString(qualifier, qualifierOffset, qualifierLength);
            // 获取值
            byte[] value = currentCell.getValueArray();
            int valueOffset = currentCell.getValueOffset();
            int valueLength = currentCell.getValueLength();
            String columnValue = Bytes.toString(value, valueOffset, valueLength);
            // 打印结果
            System.out.println("row1, " + columnFamily + ":" + columnName + ", " + columnValue);
        }

        // 3. 表扫描
        Scan scan = new Scan(Bytes.toBytes("row1"), Bytes.toBytes("row3"));
        ResultScanner resultScanner = table.getScanner(scan);
        for (Result rs : resultScanner) {
            CellScanner scanner = rs.cellScanner();
            while (scanner.advance()) {
                Cell cell = scanner.current();
                byte[] rowArray = cell.getRowArray();
                int rowOffset = cell.getRowOffset();
                int rowLength = cell.getRowLength();
                String rowKey = Bytes.toString(rowArray, rowOffset, rowLength);
                // 获取列族名称
                byte[] family = cell.getFamilyArray();
                int familyOffset = cell.getFamilyOffset();
                int familyLength = cell.getFamilyLength();
                String columnFamily = Bytes.toString(family, familyOffset, familyLength);
                // 获取列名称
                byte[] qualifier = cell.getQualifierArray();
                int qualifierOffset = cell.getQualifierOffset();
                int qualifierLength = cell.getQualifierLength();
                String columnName = Bytes.toString(qualifier, qualifierOffset, qualifierLength);
                // 获取值
                byte[] value = cell.getValueArray();
                int valueOffset = cell.getValueOffset();
                int valueLength = cell.getValueLength();
                String columnValue = Bytes.toString(value, valueOffset, valueLength);
                // 打印结果
                System.out.println(rowKey + ", " + columnFamily + ":" + columnName + ", " + columnValue);
            }
        }

        // 4. 关闭资源
        resultScanner.close();
        table.close();
        conn.close();
    }

}

总结

这两种方法的共同点在于,它们都用于从HBase中读取数据,并且可以使用过滤器来指定数据选择条件,从而返回所需的数据。它们的不同之处在于,Get()方法用于从表中读取单个行,而Scan()方法用于从表中读取多个行。当需要批量检索数据并需要对结果进行操作时,应使用Scan()方法。当需要快速检索单个行时,应使用Get()方法。

另外,可以注意到,get()方法具有更高的性能和更低的延迟,但只能检索单个行。scan()方法可以扫描多个行,但性能略低于get()。因此,在实际应用中,应根据需求选择使用适当的方法。