HBase scan优化之设置 timerange

 

 

背景

当一个表的查询,是带有时间范围的;并且此表下面数据时间跨度很大,怎样才能扫更少的数据呢?

HBase的scan操作给出了一个timerange的设置,可以只扫描在timerange范围内的文件。直接减少了扫描的文件量.

(思考:如果用户可能存在一些写入断掉/补数等行为,可以适当放宽timerange,比如表中数据是3个月,查询数据在2个小时内,那么可以timerange设置一个至少2天内的范围)


scan在命令行有一个用法是设置timerange(时间区间)

hbase shell给出的用法:

这里的时间戳应该到ms而不是s

1

scan 't1', {COLUMNS => 'c1', TIMERANGE => [13036688040001303668904000]}

功能

scan的时候只扫描时间范围内的文件

结论

写入的时候,更新memstore的timeRangeTracker的min和max 时间戳

flush的时候,timeRangeTracker的值赋值给snapshotTimeRangeTracker

写文件的时候,写入snapshotTimeRangeTracker到文件的元数据中对应的key是TIMERANGE_KEY

查询的时候客户端传递过来的scan.getTimeRange在shouldUseScanner方法中通过passesTimerangeFilter进行过滤

请求链路分析

扫描文件(查询操作)的时候涉及的代码

StoreFileScanner.shouldUseScanner

1

2

3

4

5

@Override

public boolean shouldUseScanner(Scan scan, SortedSet<byte[]> columns, long oldestUnexpiredTS) {

  return reader.passesTimerangeFilter(scan.getTimeRange(), oldestUnexpiredTS)

      && reader.passesKeyRangeFilter(scan) && reader.passesBloomFilter(scan, columns);

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

StoreFile.Reader

/**

 * Check if this storeFile may contain keys within the TimeRange that

 * have not expired (i.e. not older than oldestUnexpiredTS).

 * @param scan the current scan

 * @param oldestUnexpiredTS the oldest timestamp that is not expired, as

 *          determined by the column family's TTL

 * @return false if queried keys definitely don't exist in this StoreFile

 */

boolean passesTimerangeFilter(TimeRange tr, long oldestUnexpiredTS) {

  return this.timeRange == nulltrue:

    this.timeRange.includesTimeRange(tr) && this.timeRange.getMax() >= oldestUnexpiredTS;

}

//Reader.timeRange是从文件的metadataMap.get(TIMERANGE_KEY)  中获取的文件信息

请求堆栈

HRegionServer.scan

→HRegion.getScanner

→HRegion.instantiateRegionScanner

→RegionScannerImpl

→HStore.getScanner

→StoreScanner 构造方法

→StoreScanner.getScannersNoCompaction

→StoreScanner.selectScannersFrom

KeyValueScanner.shouldUseScanner

timerange信息在如何写入文件?

/**

 * Add TimestampRange and earliest put timestamp to Metadata

 */

public void appendTrackedTimestampsToMetadata() throws IOException {

  appendFileInfo(TIMERANGE_KEY,WritableUtils.toByteArray(timeRangeTracker));

  appendFileInfo(EARLIEST_PUT_TS, Bytes.toBytes(earliestPutTs));

}

//关键点是:Writer.timeRangeTracker

StoreFile.WriterBuilder.build() 中调用new Writer 初始化timeRangeTracker

再上层是StoreFile.WriterBuilder.trt

⬆️HStore.createWriterInTmp

第一个引用:

这里面timerange的向上跟踪可以知道是:HStore中的snapshotTimeRangeTracker

那么snapshotTimeRangeTracker的设置从何而来?

在memstore初始化的时候,初始化TimeRangeTracker

TimeRangeTracker中的时间戳最小最大值

snapshotTimeRangeTracker的值,在MemStore snapshot方法(不是hbase的snapshot,是memstore概念的snapshot,flush中用到的)中

this.snapshotTimeRangeTracker = this.timeRangeTracker;

timeRangeTracker中min和max时间戳的更新是做写入操作的时候会调用memstore.put等操作更新

compact情况下:

初始writer的时候trt为null,会new一个新的timerangeTracker

然后通过writer写数据的时候,写入每个kv会进行append操作,里面会更新trt的  min和max值

发布了52 篇原创文章 · 获赞 4 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/Gloria_y/article/details/100942444
今日推荐