9

我正在通过 HBase 执行 MR。

reducer 中的业务逻辑大量访问两个表,比如 T1(40k 行)和 T2(90k 行)。目前,我正在执行以下步骤:

1.在reducer类的构造函数中,做这样的事情:

HBaseCRUD hbaseCRUD = new HBaseCRUD();

HTableInterface t1= hbaseCRUD.getTable("T1",
                            "CF1", null, "C1", "C2");
HTableInterface t2= hbaseCRUD.getTable("T2",
                            "CF1", null, "C1", "C2");

在减少(...)

 String lowercase = ....;

/* Start : HBase code */
/*
 * TRY using get(...) on the table rather than a
 * Scan!
 */
Scan scan = new Scan();
scan.setStartRow(lowercase.getBytes());
scan.setStopRow(lowercase.getBytes());

/*scan will return a single row*/
ResultScanner resultScanner = t1.getScanner(scan);

for (Result result : resultScanner) {
 /*business logic*/
}

虽然不确定上面的代码首先是否合理,但我有一个问题 - get(...) 会比扫描提供任何性能优势吗?

Get get = new Get(lowercase.getBytes());
Result getResult = t1.get(get);

由于 T1 和 T2 将是只读的(大部分),我认为如果保留在内存中,性能将会提高。根据 HBase 文档,我将不得不重新创建表 T1 和 T2。请验证我理解的正确性:

public void createTables(String tableName, boolean readOnly,
            boolean blockCacheEnabled, boolean inMemory,
            String... columnFamilyNames) throws IOException {
        // TODO Auto-generated method stub

        HTableDescriptor tableDesc = new HTableDescriptor(tableName);
        /* not sure !!! */
        tableDesc.setReadOnly(readOnly);

        HColumnDescriptor columnFamily = null;

        if (!(columnFamilyNames == null || columnFamilyNames.length == 0)) {

            for (String columnFamilyName : columnFamilyNames) {

                columnFamily = new HColumnDescriptor(columnFamilyName);
                /*
                 * Start : Do these steps ensure that the column
                 * family(actually, the column data) is in-memory???
                 */
                columnFamily.setBlockCacheEnabled(blockCacheEnabled);
                columnFamily.setInMemory(inMemory);
                /*
                 * End : Do these steps ensure that the column family(actually,
                 * the column data) is in-memory???
                 */

                tableDesc.addFamily(columnFamily);
            }
        }

        hbaseAdmin.createTable(tableDesc);
        hbaseAdmin.close();
    }

一旦完成:

  1. 如何验证列是否在内存中(当然,describe 语句和浏览器反映了它)并从那里而不是磁盘访问?
  2. 从内存或从磁盘读取对客户端透明吗?简单来说,我需要在我的 reducer 类中更改 HTable 访问代码吗?如果是,有哪些变化?
4

2 回答 2

9

get(...) 会比扫描提供任何性能优势吗?

Get 直接对由作为参数传递给 Get 实例的行键标识的特定行进行操作。虽然 Scan 对所有行进行操作,但如果您没有通过向 Scan 实例提供开始和结束行键来使用范围查询。显然,如果您事先知道要对哪一行进行操作,效率会更高。您可以直接去那里执行所需的操作。

如何验证列是否在内存中(当然,describe 语句和浏览器反映了它)并从那里而不是磁盘访问?

您可以使用HColumnDescriptor 提供的isInMemory ()方法来验证特定 CF 是否在内存中。但是,您无法发现整个表都在内存中,以及是从磁盘还是内存中进行提取。尽管内存中的块具有最高优先级,但并不是 100% 确定所有内容始终都在内存中。这里的一件重要的事情是,即使在内存 CF 的情况下,数据也会被持久化到磁盘上。

从内存或从磁盘读取对客户端透明吗?简单来说,我需要在我的 reducer 类中更改 HTable 访问代码吗?如果是,有哪些变化?

是的。它是完全透明的。你不必做任何额外的事情。

于 2013-09-11T20:40:19.603 回答
3
  1. 就实施而言,它们之间没有实质性区别。它们都与客户端相同。
于 2013-09-11T09:35:19.847 回答