Phoenix on HBase 性能测试


1. 目的

测试 phoenix 引擎在 hbase 上的数据查询与数据写入的性能,探索 phoenix 的特性和限制。

2. 软件版本

phoenix-4.8.0-HBase-1.1

HBase-1.1.6

3. 硬件环境

四台配置相同的PC机搭建HBase集群环境,其中一台做HMaster,另外三台做Region

部件 规格
CPU Intel(R) Core(TM) i7-4820K CPU @ 3.70GHz 1U * 4Core
MEM 64G

4. 测试工具

squirrel-sql-3.5.3

apache-jmeter-3.0

5. 测试说明

使用基于 jdbc 连接的 squirrel-sql-3.5.3 进行单用户下的sql性能测试

使用基于 jdbc 连接的 apache-jmeter-3.0 进行多线程并发测试

6. 测试数据

应用场景:仅用于存放测点的档案信息,用于查询范围的条件检索过滤时使用

Reinfo 测点基础信息表 测试数据规模:5千
列名 类型 注释 是否主键
Data_id bigint 测点ID PK
DataName varchar(300) 测点名
DataType varchar(100) 测点的数据类型 (电压、电流、有功、无功等)
byzid varchar(300) 变电站编号
orgid varchar(300) 组织机构编号

应用场景:按测点编号进行查询,每次通常查询1个测点的数据,但有时也会查询几个测点的数据

CurrData 当日数据表 测试数据规模:7百万
列名 类型 注释 是否主键
Data_id bigint 测点ID PK
date_time DATE 时点 (2016-09-19 00:00,2016-09-19 00:01 … 2016-09-19 23:59) PK
data float 测试值
name varchar(300) 测点名(根据reinfo冗余字段)
DataType varchar(100) 测点的数据类型 (电压、电流、有功、无功等)(根据reinfo冗余字段)
byzid varchar(300) 变电站编号(根据reinfo冗余字段)
orgid varchar(300) 组织机构编号(根据reinfo冗余字段)

应用场景:按测点编号进行查询,每次通常查询1个测点的数据,但有时也会查询几个测点的数据

HisData 历史数据表 测试数据规模:5千万
列名 类型 注释 是否主键
Data_id bigint 测点ID PK
date_time DATE 时点:(2016-09-19 00:00 - — 2016-09-19 23:59) PK
data float 测试值
name varchar(300) 测点名(根据reinfo冗余字段)
DataType varchar(100) 测点的数据类型(电压、电流、有功、无功等)(根据reinfo冗余字段)
byzid varchar(300) 变电站编号(根据reinfo冗余字段)
orgid varchar(300) 组织机构编号(根据reinfo冗余字段)

7. 数据写入测试

评估数据写入的性能,分别对数据导入和数据插入两种方式评测。

数据导入:将文本文件数据装载至目标表。

数据插入:使用dml插入数据至目标表。

评估并发写的效率

7.1 测试条件

  • 数据导入
./psql.py hostname-2 -t CURRDATA /home/currdata1.csv
  • 数据插入

currdata1与currdata结构一致

upsert into currdata select * from currdata1;

7.2 测试结果

  • 写入时长:
记录行 720w*1 720w*2 720w*4
数据文件大小 350mb*1 350mb*2 350mb*4
并行度(进程数) 1 2 4
CASE 1:数据导入 201s 247s 282s
CASE 2:数据插入 92s 132s 158s
  • 写入效率:
记录行 720w*1 720w*2 720w*4
数据文件大小 350mb*1 350mb*2 350mb*4
并行度(进程数) 1 2 4
CASE 1:数据导入 1.74mb/s 2.83mb/s 4.96mb/s
CASE 2:数据插入 3.8mb/s 5.3mb/s 8.8mb/s

7.3 结果分析

HBase 是一个写很快的系统,并行度越高,写性能越好,经过测试发现,使用四个并行任务的情况下,集群cpu资源使用率不超过30%,磁盘繁忙程度大致在 70%~90%,所以只要条件允许,建议配置高速磁盘,尽可能地通过并行方式写入数据,最大化 Hbase 的效率。

8. K-V(RowKey)查询测试

根据表的主键(PK)进行K-V查询,场景主要有:单测点单日,单测点多日,多测点单日,多测点多日

根据电力客户提供的需求,选用720w的数据量作为测试用例,电力客户拥有 5000 个测点,每分钟一条记录,保留一天的数据,即:50006024=7200000,5kw 即一周的数据

8.1 测试示例

  • 单测点单日
select 
  data_id,date_time
  ,data 
from hisdata 
where data_id = 104708704221266921 
  and date_time <= TO_DATE('2016-09-20', 'yyyy-MM-dd') 
  and date_time >= TO_DATE('2016-09-20', 'yyyy-MM-dd') 
order by date_time;
  • 单测点多日
select 
  data_id
  ,date_time
  ,data 
from hisdata 
where data_id = 104708704221266921 
  and date_time <= TO_DATE('2016-09-20', 'yyyy-MM-dd') 
  and date_time >= TO_DATE('2016-09-18', 'yyyy-MM-dd') 
order by data_id,date_time;
  • 多测点单日
select 
  data_id
  ,date_time
  ,data 
from hisdata 
where data_id >= 104708704221266921 
  and data_id <= 104708704221266931 
  and date_time <= TO_DATE('2016-09-17', 'yyyy-MM-dd') 
  and date_time >= TO_DATE('2016-09-17', 'yyyy-MM-dd') 
order by data_id,date_time;
  • 多测点多日
select 
  data_id
  ,date_time
  ,data 
from hisdata 
where data_id >= 104708704221266921 
  and data_id <= 104708704221266930 
  and date_time <= TO_DATE('2016-09-21', 'yyyy-MM-dd') 
  and date_time >= TO_DATE('2016-09-18', 'yyyy-MM-dd') 
order by data_id,date_time

8.2 测试结果

数据量 720w 5kw
1:单测点单日 20ms 40ms
2:单测点多日 30ms 50ms
3:多测点单日 30ms 40ms
4:多测点多日 120ms 290ms

8.3 结果分析

基于 rowkey 的查询效率比较高,这也符合 HBase 的 Key-Value 特性,数据量越大,查询效率越好,数据量从 720w 到 5kw 增长了 6X,但查询耗时仅增加了 30%~100%。

但是,返回的结果集应尽量控制在 10w 以内,返回的记录行越少,响应时间越快。以 多测点多日 为例,修改sql示例中的过滤条件使其分别返回 1w,10w,100w 结果集,测试结果如下:

结果集行数 查询响应时间
1w 120ms
10w 990ms
100w 9.7s

9. 即席查询测试

即席查询的意思是即兴或临时查询。是在需要时进行的查询或搜索,而不是预先计划或准备好的查询。即席查询通常用于解决突发问题或获取即时信息。

模拟OLAP环境下的ad hoc查询,包括聚集查询,连接查询,明细查询等,即席查询主要针对非K-V方式的查询场景,同样也分为720w和5kw测试

9.1 测试示例

  • 带过滤条件和排序操作的明细查询
select 
  data_id
  ,date_time
  ,data 
from hisdata 
where byzid = '0001303' 
  and orgid = '8000041' 
  and date_time <= TO_DATE('2016-09-20', 'yyyy-MM-dd') 
  and date_time >= TO_DATE('2016-09-18', 'yyyy-MM-dd') 
order by data_id,date_time
  • 全表聚合查询
select 
  count(*) 
from hisdata
  • 关联查询
select 
  count(*) 
from hisDATA c,REINFO r 
where c.data_id = r.data_id
  • 带过滤条件的聚合查询
select 
  byzid
  ,orgid
  ,max(data)
  ,min(data)
  ,avg(data) 
from hisdata 
where DATATYPE = '无功' 
  and date_time <= TO_DATE('2016-09-20', 'yyyy-MM-dd') 
  and date_time >= TO_DATE('2016-09-18', 'yyyy-MM-dd') 
group by byzid,orgid;

9.2 测试结果

数据量 720w 5kw
带过滤条件和排序操作的明细查询 1.8s 13.3s
全表聚合查询 1.7s 11.4s
关联查询 3.3s 18.3s
带过滤条件的聚合查询 2s 16.1s

9.3 结果分析

HBase 不适合做 BI 应用中常见的 即席查询,Phoenix 进行非 K-V 类的即席查询时,是将所有的目标数据先填入内存,在内存中计算,这样的话效率主要依赖其 CBO(查询优化器)和 执行计划。测试用例采用的比较简单的查询 sql,而生产环境中的统计查询 sql 比上述用例复杂的多得多,所以,HBase 只适合 K-V 方式访问数据。

10. 并发查询

根据 HBase 的特点,仅针对 KV 方式的查询进行并发测试,为更好地评估软件的性能,将采用 5kw 的历史数据表(Hisdata)作为测试素材。以下是单用户、10用户、50用户、100用户、200用户的性能测试结果

10.1 测试示例

  • 单测点单日(短查询)
select 
  data_id
  ,date_time
  ,data 
from hisdata 
where data_id = 104708704221266921 
  and date_time <= TO_DATE('2016-09-20', 'yyyy-MM-dd') 
  and date_time >= TO_DATE('2016-09-20', 'yyyy-MM-dd') 
order by date_time;
  • 单测点多日(短查询)
select 
  data_id
  ,date_time
  ,data 
from hisdata 
where data_id = 104708704221266921 
  and date_time <= TO_DATE('2016-09-20', 'yyyy-MM-dd') 
  and date_time >= TO_DATE('2016-09-18', 'yyyy-MM-dd') 
order by data_id,date_time;
  • 多测点单日(短查询)
select 
  data_id
  ,date_time
  ,data 
from hisdata 
where data_id >= 104708704221266921 
  and data_id <= 104708704221266931 
  and date_time <= TO_DATE('2016-09-17', 'yyyy-MM-dd') 
  and date_time >= TO_DATE('2016-09-17', 'yyyy-MM-dd') 
order by data_id,date_time;
  • 多测点多日(长查询)
select 
  data_id
  ,date_time
  ,data 
from hisdata 
where data_id >= 104708704221266921 
  and data_id <= 104708704221266930 
  and date_time <= TO_DATE('2016-09-21', 'yyyy-MM-dd') 
  and date_time >= TO_DATE('2016-09-18', 'yyyy-MM-dd') 
order by data_id,date_time

10.2 测试结果

10.2.1 单用户查询结果

单位:ms avg 中位数 90% Line 95% Line 99% Line min max
单测点单日 13 7 9 13 222 6 238
单测点多日 35 25 37 44 379 22 430
多测点单日 22 14 29 45 197 11 261
多测点多日 292 277 292 312 498 263 1325

多测点多日与另外三个示例相比,响应时长要高一个量级,因此,单测点单日、单测点多日、多测点单日归为短查询的并发测试场景,多测点多日归为长查询的并发测试场景

10.2.2 10用户并发查询结果(短查询)

avg 中位数 90% Line 95% Line 99% Line min max tps
单测点单日 98 36 147 456 459 14 459 3.144456
单测点多日 250 196 260 746 806 131 858 3.171985
多测点单日 119 83 126 483 508 33 510 3.24823
总体 156 115 260 483 759 14 858 8.798686

10.2.3 10用户并发查询结果(长查询)

avg 中位数 90% Line 95% Line 99% Line min max tps
多测点多日 2355 2323 2733 2785 2869 1136 2871 1.895303
总体 2355 2323 2733 2785 2869 1136 2871 1.895303

在 10 用户并发下,长查询的 tps 只有 1.9 不到,而短查询约为 8.8。不仅如此,并发情况下,单个查询的响应时间明显增加,例如:单用户下测试单测点单日的查询响应时间均值是 13ms,10用户并发下达到了 98ms,而多测点多日的查询响应时间则由 292ms 升至 2.4s 左右。

10.2.4 50用户并发查询结果(短查询)

avg 中位数 90% Line 95% Line 99% Line min max tps
单测点单日 139 72 248 631 639 15 644 12.71294
单测点多日 789 778 971 1155 1238 38 1258 12.64191
多测点单日 231 154 380 785 790 53 793 13.00187
总体 386 174 827 903 1180 15 1258 35.42164

10.2.5 50用户并发查询结果(长查询)

avg 中位数 90% Line 95% Line 99% Line min max tps
多测点多日 19501 8001 39897 118340 125156 2366 126657 1.86617
总体 19501 8001 39897 118340 125156 2366 126657 1.86617

50 用户并发下长查询的 tps 仍然只有 1.9 不到,而响应时间均值却达到 19.5s,远远超过可接受范围,由此可见,基于测试环境的软硬件配置,长查询的并发数在 10 个左右比较适宜,最大不应超过 20。

短查询在 50 并发下,均值仍在 1s 以内,tps 升至 35,说明短查询场景还可以承受更大的并发数。

10.2.6 100用户并发(短查询)

avg 中位数 90% Line 95% Line 99% Line min max tps
单测点单日 141 69 364 601 630 11 669 20.56767
单测点多日 1603 1571 2003 2098 2174 69 2209 20.08153
多测点单日 370 311 443 982 988 42 989 20.82119
总体 704 328 1676 1907 2129 11 2209 56.69684

10.2.7 200用户并发(短查询)

avg 中位数 90% Line 95% Line 99% Line min max tps
单测点单日 189 76 244 1075 1114 22 1124 30.12956
单测点多日 3156 3099 3742 3967 4228 258 4264 29.18898
多测点单日 519 431 648 1149 1159 56 1163 30.91716
总体 1288 445 3273 3603 4095 22 4264 83.22006

在 200 用户并发下,只有单测点多日的均值超过 3s,另外两个用例的均值仍在 1s 以内,tps 达到 83。理论上讲,假如生产环境中的多日查询的频率远低于单日查询,那么此并发数还可以继续增大,限于时间和篇幅,此处不再做进一步的测试。

10.3 结果分析

对于短查询,Phoenix + HBase在 4 个节点环境下可以承受 200 个并发的压力,平均每秒能响应 83 个请求。而长查询,并发数控制在 10个左右较为合适,每秒最多响应1.9个请求。

11. 结论

  1. HBase 是一个写很快的系统,并行写/分布式写能充分发挥集群的计算资源;
  2. HBase 的 Key-Value 特性决定了基于 rowkey 或 主键 查询的效率很高;
  3. 返回的结果集越小,响应时间越快,一般建议在一万行以内;
  4. HBase 不适合做多维查询,Sql on HBase 只适合 主键 / RowKey 方式查询;
  5. 短查询和长查询的 TPS 差别巨大,优化数据模型,尽可能地优化应用中的查询为短查询。

12. 使用建议

  1. 在Phoenix中建表时,可以使用 SALT_BUCKETS 参数把数据分布到不同的 region 上,这样有利于 phoenix 并发的读写操作,示例:
CREATE  TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY, DESCRIPTION VARCHAR)  SALT_BUCKETS = 16 
  1. Phoenix 默认采用 hash join 进行多表关联,编辑 sql 时需要将最小的表放在最后,否则查询效率十分低下,未来会根据 statistics 自动优化
  2. 若无法确定关联操作中表的大小时,可以使用hint调整 join 方式,如:SELECT /*+ USE_SORT_MERGE_JOIN*/ ... 或者调大 phoenix.query.maxServerCacheBytes 参数使其能容纳大表的中间结果
  3. 主键索引要按创建时的顺序引用。如 primary key(id,name,add),那么会隐式的创建 (id),(id,name),(id,name,add) 三个索引,在 where 中用这三个条件时会用到索引,而其他组合则无法使用索引
  4. 对于二级索引,除了要按创建时的顺序引用外,如果 select 中的任意列不在索引中则无法使用索引

文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
  目录