时间:2019.4.3
场景
在《HBase 实现分页查询》中描述了一个按用户维度和时间区间查询HBase的场景,业务不断复杂后衍生出了另一个场景:需要查询一段时间段内,一个列符合特定条件的数据。
假设我们要查询的数据领域模型如下:
class
问题抽象为:从HBase查询列b=b0的数据,其中b很稀疏。
Long
行键设计与查询性能
HBase使用时最重要的莫过于Rowkey的设计,直接影响数据的存储和查询性能。
在我们的场景中,为了实现按照时间区间查询,rowkey包括用户ID和时间戳,可以使用过滤器,Scan的时候取我们需要的数据,在数据量很大的情况下,大量的KeyValue会送到过滤器筛选,必然很低效。
经验法则
- rowkey不宜过长
- 尽量将查询的维度或信息存储在rowkey中,因为rowkey筛选数据的效率最高
下面这张图来源于《HBase权威指南》,展示了KeyValue的各个方面对筛选数据性能的影响。
![800d1efe6339a5e5a6910cd0f7718c1e.png](https://i-blog.csdnimg.cn/blog_migrate/9086796a82087bbd78b09fc962869bd4.jpeg)
优化方案
回到我们的问题上来。
要查询一段时间内,列b=b0的数据,能想到有3种方法。
使用Filter
最直接的想法是Scan的时候设置列值过滤器,但是列b稀疏,所以在这样的效率很低。
rowkey中包含
可以在设计rowkey的时候纳入列b的信息,这样方法存在以下缺陷:
- 会增加rowkey的存储开销
- 一开始设计rowkey的时候,并不能考虑到所有类似情况,所以灵活性不好
映射表
本人在实际中采用的是引入一个映射表的方法,映射表中存储了对应的列b和Msg HTable的rowkey之间的关联信息。
实现
映射信息存储
BigMsg信息的存储见《HBase 实现分页查询》,之后需要同时更新映射信息。
public
查询
有了映射表,查询的时候就按时间范围先从映射表的时候Scan得到BigMsg HTable的rowkey,然后根据rowkey,使用批量Get从BigMsg HTable中查询得到最终的数据。
public
总结
- 充分挖掘应用场景,这样才能设计出良好的rowkey
- 使用映射表,其实也是变相的把需要检索的列移到了rowkey中,只不过是映射表的rowkey,这样可以不影响原始HTable的rowkey