Hbase详细笔记

  1. 负载均衡
  2. 快照
  3. 拆分
  4. 数据存储
  5. 合并
  6. 刷写
  7. 读数据流程
  8. 写数据流程
  9. 热点问题
  10. row设计
  11. 批量导入
  12. Mr整合Hbase
  13. 协处理器
  14.  

 1.负载均衡

  • 1.1有Master的LoadBalance线程周期性的在各个RegionServer间移动region维护负载均衡
  • 1.2当一个机器经过大量的插入或者删除数据以后,region经过合并,或者分裂那么机器上的region会相差很大
  • 1.3当某个region数据量过大的时候,HbaseBalance作为负载均衡的开关,会自动大概region的数据自动分配给其他数据量量较小的数据,

 

2,负载均衡的三种形式

  • 2.1自动负载均衡流程
    • 参数 在每个region里面设置两个有效参数MIN=floor(表示下限),MAX=ceil(average)表示下限
    • 循环过载机器 将region卸载到MAX数量(放到一个队列中等待分配),当region小于等于MAX时,停止排序region
    • 遍历最轻负载机器,分配region直到server达到MIN值,在大于等于MIN时,停止,这些region都输在其他region里面卸载的,可能没有足够的卸载Region让,轻负载的机器达到MIN值,如果这样,在region等于neededRegion(轻负载机器的数量)时停止.
    • 可能我们分配了卸载的region到轻负载机器,但仍然有region没有分配出去,这时候如果neededRegions是非零值,遍历负载最重的机器,从每台机器上卸载一个region,使得他们的值从MAX到MIN,
    • 如果仍然有很多Region等待分配,遍历最轻的负载机器(多台),分配region到min
    • 如果仍然有region没有分配,遍历最轻的负载机器,这次分配region到max
    • 所有server的region数量是max或者min,另外,所有大于等于max,的server保证在均衡完成后max个region,从而保证region移动的最小数量
      • 其中,轻负载指的是Region数量小于等于AVG,过载指大于等于AVG,所有的RegionServer都按照负载从大到小排序,存放在TreeMap中(保证先遍历过载Server)。
  • 2.2随机执行负载均衡
    • 用于新加入的RegionServer,随机分配Region。随机函数使用java.util.Random类实现
  • 2.3人为移动
    • 当发生经常性的查询热点问题时, 您的请求总是请求到一个服务节点上 ,我们可以把这个机器中的数据理解成热数据 ,可以任务的拆分以后手动的移动到不同的机器上 实现查询热点的负载均衡

 

Hbase中负载均衡的开关balanceSwitch默认是开启的 .

hbase.balancer.period是设定负载均衡的参数,默认为每5分钟(300000毫秒)运行一次,参数配置通过hbase-site.xml文件。具体的设置格式如下:


<property>
 
<name>hbase.balancer.period</name>
 
<value>300000</value>
 
</property>

 

2.region的拆分

  • 首先明白region是什么
    • region是一个管理起始行和结束行的逻辑数据,但真正的数据存储在hdfs里面,
  • 为什么拆分
    • HBase是以表的形式存储数据的,一张表被划分为多个region,region分布在多个region Srever
    • 上,单个reginon 只能分布在一个region Server 节点上,不能跨Region Server存放
    • region有两个重要的属性: startKey 和endKey 分别表示这个region所维护的rowkey范围,当做读写请求时,Region的两个重要属性:StartKey和EndKey,分别表示这个region所维护的rowkey范围。当做读/写请求时,寻址到该数据的rowkey落在某个start-end key范围内,那么就会定位到该范围内的region所在的Region Server上进行数据读/写
    •    随着数据的插入region中管理的数据越来越多 ,出现热点问题的概率大大增加 , 并且一个regionserver的负载过重,将region拆分 均衡到不同的节点上!
  • 如何拆分
    • 自动拆分
      • 根据大小进行拆分
        • 每当建立一个表的时候,就会在regionServer里面生成一个region,当往这个表put数据的时候,该表就会不断的产生数据,假设该表产生一亿条数据,这时候后会有大量的请求到达该region里面,这时候这台机器可能出现并发问题,
        • 这时候就需要拆分数据,这时候拆分,通常情况下,当第一条数据达到256M就开始拆,
        • 第二条数据达到2G的时候就开始拆,第三次就是6.75G的时候就开时候拆,
        • 从第四条以后,就是没达到10G的时候就开始拆.
        • 也就是在拆分的过程中,默认在到达10G的时候,就开始拆,但是在执行第一次拆分的时候,表的数据比较小,不是按照默认的数据量进行拆分的,而是第一个是256M.第二个的在到达2g.第三是6.75G的时候,知道第四个才是默认10G的时候才开始拆.
      • 拆分的算法
        • 1^3*128M 256
        • 2^3*128 2G
        • 3^3*128 6.75
      • 按照前缀拆分
        • 1.1.1.1. keyPrefixRegionSplitPolicy(自定义) 按照固定的长度进行切分
        • 1.1.1.1. DelimitedKeyPrefixRegionSplitPolicy 按照分隔符进行切分
      • 手动强制进行切分

 

1 快照原理(基于HDFS的快照)
    Hdfs的快照(snapshot)是在某一时间点对指定文件系统拷贝,快照采用只读模式,可以对重要数据进行恢复、防止用户错误性的操作。

      快照分两种:一种是建立文件系统的索引,每次更新文件不会真正的改变文件,而是新开辟一个空间用来保存更改的文件,一种是拷贝所有的文件系统。Hdfs属于前者。

Hdfs的快照的特征如下:

快照的创建是瞬间的,代价为O(1),取决于子节点扫描文件目录的时间。
当且仅当做快照的文件目录下有文件更新时才会占用小部分内存,占用内存的大小为O(M),其中M为更改文件或者目录的数量;
新建快照的时候,Datanode中的block不会被复制,快照中只是记录了文件块的列表和大小信息。
快照不会影响正常的hdfs的操作。对做快照之后的数据进行的更改将会按照时间顺序逆序的记录下来,用户访问的还是当前最新的数据,快照里的内容为快照创建的时间点时文件的内容减去当前文件的内容。
 

 


1 snapshot  "tb_spl2" , "spl_info"  拍摄快照    参数一表  参数二 快照名
 
2 hbase(main):019:0>  list_snapshots   列举出所有的快照
SNAPSHOT                              TABLE + CREATION TIME                                                                                       
      spl_info                             tb_spl2 (2020-06-13 11:22:52 +0800)    
 
3 restore_snapshot  "spl_info"  恢复快照
 

 

 

建表时指定预分region

在shell客户端

  hbase> create 'ns1:t1', 'f1', SPLITS => ['10', '20', '30', '40']
  hbase> create 't1', 'f1', SPLITS => ['10', '20', '30', '40']
    byte[][] keys = new byte[][]{"e".getBytes(), "m".getBytes(), "t".getBytes()};
    // 建表    指定预分region的key(数组)
    admin.createTable(tableDescriptor, keys);

 

HBase的合并

hbase中所有的操作都是写操作 ,在所有的操作中有对应的put delete 标记 !查询数据的时候不会显示delete标记的数据 !当Hfile合并的时候才会将删除的数据真正的删除掉!

5.1 hfile合并
数据加载到memstore,数据越来越多直到memstore占满,再写入硬盘storefile中,每次写入形成一个单独Hfile,当Hfile达到一定的数量后,就会开始把小Hfile合并成大Hfile,因为Hadoop不擅长处理小文件,文件越大性能越好。

触发compaction的方式有三种:Memstore刷盘、后台线程周期性检查、手动触发。
 

1.Memstore Flush:

应该说compaction操作的源头就来自flush操作,memstore flush会产生HFile文件,文件越来越多就需要compact。因此在每次执行完Flush操作之后,都会对当前Store中的文件数进行判断,一旦文件数大于配置,就会触发compaction。需要说明的是,compaction都是以Store为单位进行的,而在Flush触发条件下,整个Region的所有Store都会执行compact,所以会在短时间内执行多次compaction。
 

 

2.后台线程周期性检查:

后台线程定期触发检查是否需要执行compaction,检查周期可配置。线程先检查文件数是否大于配置,一旦大于就会触发compaction。如果不满足,它会接着检查是否满足major compaction条件,简单来说,如果当前store中hfile的最早更新时间早于某个值mcTime,就会触发major compaction(默认7天触发一次,可配置手动触发),HBase预想通过这种机制定期删除过期数据。
 

3.手动触发:

一般来讲,手动触发compaction通常是为了执行major compaction,一般有这些情况需要手动触发合并

是因为很多业务担心自动major compaction影响读写性能,因此会选择低峰期手动触发;

也有可能是用户在执行完alter操作之后希望立刻生效,执行手动触发major compaction;

是HBase管理员发现硬盘容量不够的情况下手动触发major compaction删除大量过期数据;
 

在合并的过程中会做什么操作?

在合并的过程中会抛弃删除标识的行和版本过旧的行
(1)可以预先定义版本的个数,超过这个值就抛弃
(2)还可以预先定义版本的时间长短,超过这个时间就抛弃,合并完后形成更大的storefile,当达到数量再次合并,直到storefile容量超过一定阀值后会把当前的Region进行分裂为2个并由Hmaster(hbase数据库主控节点)分配到不同的HRegionServer服务器处理实现负载均衡。

如果在合并过程中恰好有涉及到有关storefile的查询发生的话,我们先是把小storefile加载到内存中进行合并此时如有用户访问可以在内存中检索相关数据返回给用户,我们可以想象在内存中做一个独立镜像备份专门提供被查询需求,另一个主体在另一块内存空间里进行合并,当合并完成后释放备份的内存空间,返回到原来的状态。
 

 

5.2.1 那为什么需要合并Region呢
这个需要从Region的Split来说。当一个Region被不断的写数据,达到Region的Split的阀值时(由属性hbase.hregion.max.filesize来决定,默认是10GB),该Region就会被Split成2个新的Region。随着业务数据量的不断增加,Region不断的执行Split,那么Region的个数也会越来越多。

一个业务表的Region越多,在进行读写操作时,或是对该表执行Compaction操作时,此时集群的压力是很大的。这里笔者做过一个线上统计,在一个业务表的Region个数达到9000+时,每次对该表进行Compaction操作时,集群的负载便会加重。而间接的也会影响应用程序的读写,一个表的Region过大,势必整个集群的Region个数也会增加,负载均衡后,每个RegionServer承担的Region个数也会增加。

因此,这种情况是很有必要的进行Region合并的。比如,当前Region进行Split的阀值设置为10GB,那么我们可以对小于等于10GB的Region进行一次合并,减少每个业务表的Region,从而降低整个集群的Region,减缓每个RegionServer上的Region压力。
 

 

那么我们如何进行Region合并呢?HBase有提供一个合并Region的命令,具体操作如下:

# 合并相邻的两个Region
hbase> merge_region 'ENCODED_REGIONNAME', 'ENCODED_REGIONNAME'
# 强制合并两个Region
hbase> merge_region 'ENCODED_REGIONNAME', 'ENCODED_REGIONNAME', true

 

 

3.1 Minor合并:
是把最后生成的几个小的StoreFile文件 合并一个更大的StoreFile, 默认同时合并的文件数为10, 主要控制参数如下;
hbase.hstore.compaction.min最小合并文件 数量大小, 默认为3
hbase.hstore.compaction.max 最大合并文件 数量大小, 默认为10
hbase.hstore.compaction.max.size 最大合并文件 的大小 , 默认值 为Long.MAX_VALUE
hbase.hstore.compaction.min.size 最小合并文件 的大小, 默认值是memStore刷写的大小, 它是一个阈值, 它包含所有小于限制的文件 ,直到达到每次压缩允许的总文件数量
 

 

 

3.2 Major合并:
是把整个Store中所有StoreFile文件 合并成一个单独的StoreFile文件,后台定时任务定期检查, 这个检查周期是由下面这两人个参数决定
hbase.server.thread.wakefrequency * hbase.server.thread.wakefrequency.multiplier(默认值为1000)
 

6 刷写
一个Store有一个MemStore,保存数据修改。当flush后,当前MemStore就被清理了。MemStorez中的数据按 RowKey 字典升序排序。

HBase需要将写入的数据顺序写入HDFS,但因写入的数据流是未排序的及HDFS文件不可修改特性,所以引入了MemStore,在flush的时候按 RowKey 字典升序排序进行排序再写入HDFS。

充当内存缓存,在更多是访问最近写入数据的场景中十分有效

2 刷写时机
Region级别-跨列族
Region内的其中一个MemStore大小达到阈值(hbase.hregion.memstore.flush.size),该Region所有MemStore一起发生Flush,输入磁盘。默认大小是128M !

RegionServer级别
当一个RS内的全部MemStore使用内存总量所占比例达到了阈值(hbase.regionserver.global.memstore.upperLimit),那么会一起按Region的MemStore用量降序排列flush,直到降低到阈值(hbase.regionserver.global.memstore.lowerLimit)以下。

另有一个新的参数hbase.regionserver.global.memstore.size,设定了一个RS内全部Memstore的总大小阈值,默认大小为Heap的40%,达到阈值以后就会阻塞更新请求,并开始RS级别的MemStore flush,和上述行为相同。

HLog-WAL文件
当region server的WAL的log数量达到hbase.regionserver.max.logs,该server上多个region的MemStore会被刷写到磁盘(按照时间顺序),以降低WAL的大小。否则会导致故障恢复时间过长。

手动触发
通过HBase shell或Java Api手动触发MemStore flush

 

 

读数据的基本流程

 客户端请求zookeeper,zookeeper返回meta表所在的位置信息

2 客户端获取meta表的位置信息以后,请求META表所在的RegionServer机器获取存储数据的元数据表META

3 客户端获取META表,并缓存到客端(方便下次使用),这时客户端就知道自己要的数据在哪个Regionserver的哪个Region上

4 客户端根据元数据信息,请求对应的Regionserver上的region获取数据

    4.1 从MemStore中查看是否有要读取的数据,如果有则将数据写入到缓存块中 ,返回客户端

    4.2 如果内存中没有要读取的数据,则去缓存块中去查看是否有自己的要的数据 ,如果有就返回客户端

    4.3 如果缓存中依然没有我们要找的数据 ,那么这个时候就去HDFS中的Hfile中读取数据

    4.4  从Hfile中获取数据以后 ,也会将查询的结果写到缓存块中 , 再返回给客户端

HFile文件所在的位置具体如下:
 

 

7.2 布隆过滤器 

使用很少的空间来实现从大量文件中定位数据一定不再某些文件中 ,极可能在某些文件中

每次flush都会在表对应的文件夹中生成Hfile文件 , 可能一个表中的Hfile文件会很多 ,为了快速的确定数据在哪个Hfile中, HBASE引入了布隆过滤器!

如上图所示,布隆过滤器不能明确指出哪一个文件一定包含所查找的行键,布隆过滤器的结果有误差存在。当布隆过滤器判断文件中不包含对应的行时,这个答案是绝对正确的;但是,当布隆过滤器判断得到文件中包含对应行时,这个答案却有可能是错的。也就是说,HBase还是有可能加载了不必要的块。尽管如此,布隆过滤器还是可以帮助我们跳过一些明显不需要扫描的文件。另外,错误率可以通过调整布隆过滤器所占空间的大小来调整,通常设置错误率为1%。

需要注意的是,使用布隆过滤器,并不一定能立即提升个别的get操作性能,因为同一时间可能有多个客户端向HBase发送请求,当负载过大时,HBase的性能受限于读磁盘的效率。但是,使用了布隆过滤器之后,可以减少不必要的块加载,从而可以提高整个集群的吞吐率。并且,因为HBase加载的块数量少了,缓存波动也降低了,进而提高了读缓存的命中率。

布隆过滤器其实就是将目标数据经过布隆大哥自己写的hash算法,
这个算法是将
将一个8位比特位1的数据 也就是8个1(这个是比特位的1)(数量根据需要的成功率会有变化),
然后将每个比特位通过他的算法对应到一个长度位64k的二进制数组上(长度也随成功率自行调整) ,
例如
https://google.com/abc/d
通过布隆过滤器时
可以计算出8个位置
1 2 3 9 15 20 31 32(仅举例)
那么我们就将8个比特位分别插入到这些位置
 

          例如下图

  如果 hello ---> hashcode的值是    12     12位置是1    说明hello极大的可能存在

0    0    0    0    0    0    0    0    0    0    0    0    1    0    0    1    0    0    0    1    0    0    0    0    1    0    0    0    0    0
0    1    2    3    4    5    6    7    8    9    10    11    12    13    14    15    16    17    18    19    20    21    22    23    24    25    26    27    28    29

 

如果下次存在经过这个过滤器的时候, 8个比特位完全重复的, 那么大概率是已经通过一次这个过滤器了, 大概率不代表完全确定, 因为可能存在偶然结果, 但是我们可以通过适当增大二进制数组的长度, 来确保尽量可靠

Hbase之所以会用到这个布隆过滤器是因为, region server 的内存在很多情况下会自动将内存中的热数据写入到文件中, 时间一长会造成一个region目录/一个列族目录下存在多个文件, 而且这些个文件可能存在重复数据, 让我们查询数据的时候, 显然盲目遍历的去查找是不科学的, Hbase就选择在写入每个文件时, 同时通过了布隆过滤器, 也就是每个文件都有一个布隆过滤器的二进制数组, 所以当Hbase查询数据时, 它会去选择读取结果全部命中布隆过滤器二进制数组的对应的文件, 这样虽然不能保证100%, 但是最坏的结果也就是多读了几个文件, 相比遍历, 效率显著提高!
 

写数据流程


1 客户端请求ZK集群获取存储元数据信息的META表所在的机器

2 请求META表所在的机器,下载META表到客户端并缓存在本地

3 客户端解析META表, 获取要读取的数据所在的RegionServer机器

4 请求RegionServe确定读取的数据在哪个region中

5 先从内存对象中获取数据 , 如果没有再查看缓存区域 ,缓存中没有再去Hfile中读取数据 , 为了快速的确定数据在哪个Hfile中, HBASE引入了布隆过滤器

6 如果数据是从Hfile中读取, 会将数据缓存在缓存区中再返回给客户端 , 以便下次查询的时候提高查询效率
 

热点问题

热点产生的原因

当表被创建时,HBase默认只会为该表分配一个region,那么,初始状态时所有的请求都会集中在一个Region Server上,当大量数据写入时,该节点将成为热点,甚至产生f

当表被创建时,HBase默认只会为该表分配一个region,那么,初始状态时所有的请求都会集中在一个Region Server上,当大量数据写入时,该节点将成为热点,甚至产生full gc。

当然,region热点不仅体现在创建表阶段。对于一张拥有很多region的大表来说,其在Region Sever上的分布往往不会十分均匀,region较多的Region Server在有大量数据写入时,它的负载也会大于其他region数少的Region Server,这也是热点。

 

热点问题的解决办法

如果知道了HBase数据表的key分布情况,可以根据需要,规划要拆分成多少个region,每个region的起始key是多少,那么就可以在建表时对HBase进行region的预分区,这样就能避免热点,提高数据写入效率。

合理设计rowkey能让各个region的并发请求平均分配,使IO效率达到最高。比如,key的前几位字符串都是从0001~0010的数字,这样就可以分成10个region,使用SPLISTS,如下:

create't1','f1',{SPLITS=>['0001','0002','0003','0004','0005','0006','0007','0008','0009']}

如果分区分区信息比较多,那么可以通过指定分区文件来做:

create't1','f1',{SPLITS_FILE=>'region_split_info.txt'}

region_split_info.txt文件内容如下,每行都是key取值范围的分割点。文件第一行为第一个region的endkey,每行依次类推,最后一行的0009为倒数第二个region的endkey,同时也是最后一个region的startkey。

cat region_split_info.txt

0001|

0002|

0003|

0004|

0005|

0006|

0007|

0008|

0009|

在HBase Master Web UI页面上查看,可以看到第一个region是没有startkey,最后一个region是没有endkey的。

 

10 row设计

用来表示唯一一行记录的主键,HBase的数据是按照RowKey的字典顺序进行全局排序的,所有的查询都只能依赖于这一个排序维度。

ROWKEY设计原则
   一条数据的唯一标识就是 rowkey,那么这条数据存储于哪个分区,取决于 rowkey 处于哪个一个预分区的区间内,设计 rowkey 的主要目的 ,就是让数据均匀的分布于所有的 region 中,在一定程度上防止数据倾斜。接下来我们就谈一谈 rowkey 常用的设计方案。

 

1. rowkey 长度原则
  Rowkey 是一个二进制码流,Rowkey 的长度被很多开发者建议说设计在 10~100 个字节,不过建议是越短越好,不要超过 16 个字节,存为byte[]字节数组,一般设计成定长的。

  原因如下:

    1、数据的持久化文件 HFile 中是按照 KeyValue 存储的,如果 Rowkey 过长比如 100 个字 节,1000 万列数据光 Rowkey 就要占用 100*1000 万=10 亿个字节,将近 1G 数据,这会极大 影响 HFile 的存储效率;

    2、MemStore 将缓存部分数据到内存,如果 Rowkey 字段过长内存的有效利用率会降低, 系统将无法缓存更多的数据,这会降低检索效率。因此 Rowkey 的字节长度越短越好。

    3、目前操作系统是都是 64 位系统,内存 8 字节对齐。控制在 16 个字节,8 字节的整数 倍利用操作系统的最佳特性。
 

2. rowkey 散列原则
  如果 Rowkey 是按时间戳的方式递增,不要将时间放在二进制码的前面,建议将 Rowkey 的高位作为散列字段,由程序循环生成,低位放时间字段,这样将提高数据均衡分布在每个 Regionserver 实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息将产生所有 新数据都在一个 RegionServer 上堆积的热点现象,这样在做数据检索的时候负载将会集中 在个别 RegionServer,降低查询效率。

      row key是按照字典序存储,因此,设计row key时,要充分利用这个排序特点,将经常一起读取的数据存储到一块,将最近可能会被访问的数据放在一块。

举个例子:如果最近写入HBase表中的数据是最可能被访问的,可以考虑将时间戳作为row key的一部分,由于是字典序排序,所以可以使用Long.MAX_VALUE - timestamp作为row key,这样能保证新写入的数据在读取时可以被快速命中。

3. rowkey 唯一原则
  必须在设计上保证其唯一性。rowkey 是按照字典顺序排序存储的,因此,设计 rowkey 的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问 的数据放到一块。
 

 

4 避免热点问题

调研数据特点 , 调研业务特点, 是查询多还是写入场景多 ,是否有并发操作 ,并发的频次和周期,并发量 ,根据数据特点和查询的维度设计表的行建! 详细查看热点文解决方案

 

13协处理器
13.1 简介 
可理解为服务端的拦截器,可根据需求确定拦截点,再重写这些拦截点对应的方法

协处理器允许在region server上运行自己的代码,更准确地说是允许用户执行 region级的操作,并且可以使用与RDBMS中触发器(trigger)类似的功能

协处理器分两种类型,系统协处理器可以全局导入region server上的所有数据表,表协处理器即是用户可以指定一张表使用协处理器。协处理器框架为了更好支持其行为的灵活性,提供了两个不同方面的插件。

一个是观察者(observer),类似于关系数据库的触发器。

另一个是终端(endpoint),动态的终端有点像存储过程。Observer : 在region server上执行,而且是自动执行Endpoint:  在region server上执行,但是要由客户端通过请求来调用执行
 

观察者(Observers)

RegionObserver:针对Region的观察者,可以监听关于Region的 操作。

RegionServerObserver:针对RegionServer的观察者,可以监听 整个RegionServer的操作。

MasterObserver:针对Master的观察者,可以监听Master进行的 DDL操作。

WALObserver:针对WAL的观察者,可以监听WAL的所有读写操 作。

BulkLoadObserver:BulkLoad是采用MapReduce将大量数据快速 地导入HBase的一种方式。BulkLoadObserver可以监听BulkLoad行为。

EndpointObserver:可以监听EndPoint的执行过程。在此我并没有列出这些接口的所有基本实现类,只列出最常用的两种基本实现类:BaseRegionObserver:实现了RegionObserver接口的所有需要实 现的方法,并给出了最简单实现。

BaseMasterObserver:实现了MasterObserver接口的所有需要实 现的方法,并给出了最简单的实现。

终端

只有一个接口CoprocessorService,并且没有提供基本的实现类。 该接口只有一个方法需要实现:getService,该方法需要返回Protocol Buffers(Google开发的第三方库,用来实现一种数据传输格式,类似 XML,但是比XML更节省传输资源)的Service实例,所以实现Endpoint 之前,还需要了解一下Protocol Buffers的相关知识作为基础。
 

3,3 二级索引案例
13.3.1什么是二级索引
HBase的查询都是通过RowKey(要把多条件组合查询的字段都拼接在RowKey中显然不太可能),或者全表扫描再结合过滤器筛选出目标数据(太低效),所以通过设计HBase的二级索引来解决这个问题。

多个查询条件构成了多维度的组合查询,需要根据不同组合查询出符合条件的数据。

例如:

  按照电影维度查询数据适合,但是按照uid就不适合 , 使用二级索引分两步查询实现高效获取数据,因为两次都是通过ROWKEY查询的数据
 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值