一、介绍
Phoenix是什么?
Phoenix=HBase+SQL
可以理解为在HBase的上层套了一层SQL引擎,支持用sql方式访问HBase。
支持毫秒到秒级的低延时OLTP和操作型分析查询
Phoenix能做什么?
1.支持标准的SQL语法 转为HBase API
2.支持将算子、过滤条件下推到server端,并行执行
3.二级索引、分页查询、Join、轻量级事务等能力
结构:
- 客户端 : JDBC程序或命令行,将SQL进行解析优化生成QueryPlan,进而转化为HBase Scans,调用HBase API下发查询计算请求,并接收返回结果;
- 服务端 :
- Phoenix元数据表(如图中SYSTEM.CATALOG) 储存Phoenix表与元数据表的映射,建表时的信息和表状态等。
- Phoenix协处理器(Endpoint类型) 处理二级索引、聚合及JOIN计算等。
优点:
1.SQL门槛低,使用便利,用户接入成本低
2.用户无需关心 rowkey设计, 热点、分页,简单join等的设计
3.部分场景下读取性能比直接读HBase有提升
为什么部分场景比直接读HBase快?
1.编译SQL成为原生HBASE的可并行执行的scan
2.计算下推,server端的coprocessor执行聚合
3.下推where过滤条件到server端的scan filter上
4.利用统计信息优化、选择查询计划
5.二级索引 提高非行键查询性能
6.skip scan 能力来优化IN,LIKE和OR查询
7.可选的对行键进行加盐以实现负载均衡,避免热点
缺点:
1.写入性能相比HBase下降: 写入时需要对字段做一定处理,对状态表更新,性能有一定下降,在20%以内
2.复杂join、groupby 性能低: 扫描数据量大
3.与二级索引的一致性不够完善,仅有3种策略
4.部分场景读性能有提升,但如果用户将自己的需求以HBase原生API实现,性能相较于Phoenix是更优的。Phoenix内部经过解析,优化执行计划等一些操作是有一定耗时的。
如何使用Phoenix?
1.JDBC API
2.使用Python编写的命令行工具(sqlline, sqlline-thin和psql等)
3.SQuirrel
二、读写链路
读:
客户端:
1.接收sql
2.Parser 解析sql ,生成执行计划QueryPlan
3.Optimizer 优化查询计划(判断索引表是否可用,如可用则替换为索引表的查询计划)
4.转化成HBase 的 scan,发送RPC请求到RegionServer上
5.如有orderby count等聚合计算,请求到对应的协处理器方法上
服务端:
1.接受RPC请求,处理查询
2.聚合计算先在多个rs上计算后,把多个计算后的结果返回给客户端,客户端再计算。
写:
客户端:
1.接收sql
2.解析转成HBase的put ,发送RPC请求到RegionServer上(主表)
服务端:
1.接受RPC请求,处理主表的Put
2.协处理器的后台线程,定时将新写入主表的数据读出,再put到索引表对应的HBase表上。
三、二级索引
适合用索引表的场景
- 单个主表满足不了的查询
- 过滤条件几乎固定的,不在主表主键字段上的查询
phoenix表的主键是由一个或多个字段组成,适合按rowkey,或前缀部分rowkey过滤查询。但如有其他查询场景无法指定前缀rowkey,要按其他字段做查询条件,查询需要扫描表的全量数据。hbase不适合扫描全表操作,数据量稍微大点扫描全表就不可用了。
使用索引表,查询时可以根据索引表的主键快速扫描出需要的数据。
原理:
1.创建索引表时指定查询场景下where 的字段和select的字段,最终索引表主键由做where条件的字段和主表主键字段一起组成,二级索引表底层也是HBase表。
2.查询时客户端解析sql,判断是否有合适的二级索引,如果有则优化查询计划将scan落到索引表对应的HBase表上。
4.在索引表对应的HBase表上,索引表主键相当于rowkey,按rowkey进行扫描即可。
3.server端的协处理器的后台线程会定时将新写入主表的数据同步到二级索引表中。(历史数据可通过异步补二级索引程序跑)
同步/异步:
1.异步建索引表比同步建索引表多加了ASYNC标识
2.异步索引表建好后一直是building状态(可写不可读),
3.单纯依赖phoenix内部补数据线程补数据很慢,且会增加集群负载,通常直接跑异步二级索引,跑完后索引表就是active状态
4.新建的主表一般建同步的索引表,如果主表已经有数据 就建异步索引表。
(如果主表有数据 建了同步的索引表,建索引表时会补数,补数完成才创建成功,耗时很久,若有同时有新写入可能追不上)
四、常用运维手段及常见问题
1. 异步补二级索引
什么时候需要跑异步二级索引?
建好异步索引表后,需要补历史主表数据的情况下需要跑。
如何跑?
使用Phoenix的内置工具IndexTool执行。
如有需求可联系@数据引擎服务号v2 。
原理:
IndexTool是phoenix内置的工具,用作Build主表全量索引数据:
工具内使用snapshot,后起IndexTool MR job,output并bulkload到对应hbase集群索引表,对regionserver读写无压力。
2.主表写阻塞或二级索引表被禁用
为什么会发生?
受主表索引表一致性策略影响,默认策略是: 当写索引表失败后,disable索引表,不阻塞主表写。
这样带来的风险是:当写索引表失败时,索引表被disable,所有查询落到主表上,出现扫全表情况,查询慢超时,rs宕机,还可能影响其他业务。
最近在推使用推荐策略:当写索引表失败后,不disable索引表,阻塞主表写。 这样不会影响查询,只是新的写入受影响。
ps:第3种策略是disable索引表,不阻塞主表写,这样数据会不一致,不建议使用。
影响: 查询时落到主表会扫全表
恢复:
1.确定写索引表失败原因,机器问题就挪出。更新索引表状态为active
2.写入还是失败可能需要重启rs(主表和索引表尽量在不同分组,避免滚动升级期间写索引表失败引发一系列问题)
3.二级索引表不可用及恢复
现象: 索引表禁用时间戳(INDEX_DISABLE_TIMESTAMP)>0
影响: sql的查询落到了主表上,没有落到索引表上。由于主键不同,落到主表上后会扫全表,带来rs压力变大甚至宕机的风险。
需要做:
1.确定索引表状态(查system.catalog表)
2.恢复主表下所有索引表状态为active(alter set)
alter index IDX_P002 ON TEST_NS.P003 ACTIVE;
3.如有主表索引表数据不一致的风险,需要补数据。
索引表被disable期间,如果继续写数据,数据会有不一致的情况。
状态: