Phoenix可用性测试报告
——种基于HBase的SQL中间层开源插件
目录
3.3 Phoenix VS HBase VS Hive 基于主键查询7
3.5 Phoenix VS Hive基于列模糊带函数查询8
1. 文档说明
1.1 编写目的
了解Phoenix的基本功能,应用范围和基本性能。为后续项目应用Phoenix提供参考。
1.2 适用范围
本系统测试报告的预期读者是:HBase&Hive应用、设计、开发、测试人员。
1.3 参考资料
Phoenix在github上的说明及资料:
https://github.com/forcedotcom/phoenix/wiki。
http://forcedotcom.github.com/phoenix/index.html。
1.4 测试目的
Ø Phoenix的环境部署依赖;
Ø Phoenix的可用性及应用范围;
Ø Phoenix&HBase与Hive&HBase整合的性能对比;
2. 测试说明
2.1 测试类型
测试类型 |
测 试 内 容 |
测 试 目 的 |
测试方法 |
功能测试 |
Phoenix基于JDBC接口 协议的增删改查 |
核实Phoenix对JDBC的实现情况 |
手工编码测试 |
性能测试 (粗略) |
测试基于主键范围、列值模糊查询及简单Max、Min函数查询性能。 |
掌握Phoenix的优势与劣势,在合适的环境下充分利用Phoenix优势 |
手工编码测试 |
2.2 硬件环境
2.3 软件环境
JAVA版本 |
1.6.0_33-b04 |
Hadoop版本 |
Hadoop 2.0.0-cdh4.1.1 |
HBase版本 |
HBase 0.94.2-cdh4.2.0 |
Hive版本 |
hive-0.9.0-cdh4.1.1 |
Phoenix版本 |
1.0 |
注:Phoenix必须依赖于JDK1.6 or higher,HBase-0.94.2 or higher。
2.4 部署环境
基于以上的软件版本,部署Phoenix非常简单,将phoenix-[version].jar分别拷贝至HBase中master节点和regionserver节点的lib目录下,重启hbase即可生效。
将phoenix-[version]-client.jar拷贝至客户端类路径下即可。
3. 测试结果及分析
3.1测试类型
建表说明:若需采用Phoenix的JDBC查询,务必采用Phoenix客户端的建表语句,而HBase自身的建表语句生成的表,在Phoenix里不识别,但是通过Phoenix创建的表,在HBase客户端却可以识别。因此Hive建外部表也必须依赖于Phoenix所建的表。
另外,数据类型也存在差异,HBase自身仅支持字符串,而Phoenix通过额外的编码,可支持比较复杂的数据类。【关于Phoenix,详见本文第5章】
建表语句 |
|
Phoenix |
CREATE TABLE PHOENIXTABLE_TEST ( id VARCHAR(25) not null primary key, name VARCHAR(255) , addr VARCHAR(500), date TIMESTAMP not null ) VERSIONS=10 |
HBase |
{NAME => 'PHOENIXTABLE_TEST', coprocessor$4 => 'phoenix.jar|com.salesforce.phoenix.join.HashJoiningRegionObserver|1|', coprocessor$3 => 'phoenix.jar|com.salesforce.phoenix.coprocessor.GroupedAggregateRegionObserver|1|', coprocessor$2 => 'phoenix.jar|com.salesforce.phoenix.coprocessor.UngroupedAggregateRegionObserver|1|', coprocessor$1 => 'phoenix.jar|com.salesforce.phoenix.coprocessor.ScanRegionObserver|1|', FAMILIES => [{NAME => '_0', DATA_BLOCK_ENCODING => 'FAST_DIFF', VERSIONS => '10', KEEP_DELETED_CELLS => 'true'}]} |
Hive |
CREATE EXTERNAL TABLE PHOENIXTABLE_TEST ( id string, name string, addr string , date TIMESTAMP ) STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' WITH SERDEPROPERTIES ("hbase.columns.mapping"=":key,_0:NAME,_0:ADDR, _0:DATE ") TBLPROPERTIES ("hbase.table.name" = "PHOENIXTABLE_TEST"); |
本文主要集中测试写入和查询两个方面做对比。删除操作本次未做详细测试(因为在NoSQL的环境下很少做常规性删除)。
3.2 Phoenix VS HBase 写入
写入说明:
a.Phoenix采用PreparedStatement一次写入30w条数据(每条数据90字节左右)
b.HBase采用自身客户端API一次写入30w条数据(与Phoenix基本一致)
由图可知,Phoenix的写入性能与HBase自身客户端相比,略低。
3.3 Phoenix VS HBase VS Hive 基于主键查询
查询说明:三者同时基于主键范围查询。为保持属性设置一致,fetchSize统一为50(因为Hive源码固化了此参数)
a.Phoenix与Hive采用PreparedStatement,查询语句【select * from PHOENIXTABLE_TEST where ID >="10500000" and ID <="10600000"】
b.HBase采用Scan s = new Scan(Bytes.toBytes("10500000"),Bytes.toBytes("10600000"));
由图可以看出,基于纯主键的查询,HBase的Scan性能是最高的,得益于其天生的一级索引(基于RowKey)属性。而Phoenix与HBase很接近,但是Hive差距很大。
3.4 Phoenix VS Hive 基于列模糊查询
查询说明:由于HBase局限于自身简单的查询机制,在对列值模糊查询时,HBase显得十分笨重(要么全局扫描,要么限制主键范围,但这取决于业务背景和主键设计),因此在基于列值模糊查询时,与Phoenix和Hive没有可比性。
Phoenix和Hive同时基于列值进行模糊查询,采用PreparedStatement,语句为(fetchSize=50):select * from PHOENIXTABLE_TEST where ADDR like “%59_9%”
由于Phoenix查询是整合HBase自身的API,在性能上具有天生的优势,并且做到实时返回数据;而Hive采用的是离线批量处理的重框架MapReduce,其启动和执行需要更多的资源和时间,并且只能在MR执行完成以后,数据才能返回。因此,在一定数据和环境约束下,性能反而比较低。
3.5 Phoenix VS Hive基于列模糊带函数查询
Phoenix和Hive同时基于列值进行模糊查询,采用PreparedStatement,语句为(fetchSize=50):select MIN(ID) ,MAX(ID) from PHOENIXTABLE_TEST where ADDR like '%59_9%' GROUP BY ID
分析同上。
4. 结论
Phoenix对单表操作具备很高性能优势,通过标准的SQL和JDBC,简单易用。
仅对单表和部分SQL特征支持。
根据Phoenix的优势和劣势可以得出,在HBase自身客户端API可用的环境下,Phoenix一样实用,且性能并没有损耗太多。因此,Phoenix不失是一种值得逐步推广应用的插件。
由于它自身开源,其服务端代码量不多,客户端代码量相对较多。因此,可视项目应用需要对Phoenix进行自定制的改进!
5. Phoenix简单介绍
以下部分由我个人整理,仅供参考,部分内容会随着我对Phoenix源码的深入陆续改进。
Phoenix是Salesforce.com开源的基于JAVA开发SQL中间层,实现JDBC协议接口,可在HBase上执行SQL(当前仅支持对单表的增删改查以及部分函数)语句,几乎达到实时响应和交互。其查询做到实时响应的基本原理是:将一个相对于HBase客户端比较复杂的查询转换成一些列Scan,结合建表时植入的corprocessor和定制的filter进行查询,并经过有序地汇集各scan结果再输出给调用程序的ResultSet,从而快速完成查询。内部核心是整合HBase自身的API,而没有采用笨重的MapReduce。
Phoenix致力于打造成访问HBase数据的行业标准的API。
Phoenix目前仅支持对单表的SELECT、UPSERT VALUES、UPSERT SELECT、DELETE、CREATE、DROP、ALTER TABLE、EXPLAIN。以及一些有HBase表、列族特色的一些SQL选项。
目前还不支持Join、Derived tables()、Relational operators(Union, Intersect, Minus) 等。
Phoenix目前支持AVG、COUNT、MAX、MIN、SUM、SUBSTR、TRIM、LTRIM、TRIM、LENGTH、REGEXP_SUBSTR、REGEXP_REPLACE、ROUND、TRUNCATE、TO_CHAR、TO_DATE、CURRENT_DATE、CURRENT_TIME等。
Phoenix目前支持INTEGER、UNSIGNED_INT、BIGINT、UNSIGNED_LONG、DECIMAL、BOOLEAN、TIME、DATE、TIMESTAMP、VARCHAR、CHAR、BINARY。
Phoenix目前支持Table和View,但是基于View查询性能远低于Table。Phoenix的所有scheme都是多版本支持的。
另外,HBase中的表若需Phoenix提供SQL的查询支持,务必通过Phoenix的Create语句创建,否则Phoenix的SQL会报表不存在的异常。其实这个不难理解,其一,HBase的表中列族下的列是完全动态的,每一行都可能不一样,因此,由HBase表无法准确反向关联至标准的SQL;其二,为了充分利用HBase 的corprocessor,需在建表时写入元数据。其三,Phoenix提供scheme多版本支持,需要一个元数据表,即Phoenix自身的SYSTEM.TABLE,其作为一个HBase的表存在于HBase中。
通过Phoenix创建的表,其主键为HBase表的row key,其他列为默认列族”_0”下的列。因此,在Phoenix中创建的表,通过HBase客户端亦可正常访问。不过要特别注意:HBase自身默认存储的数据类型都是字符串,但Phoenix支持更多的数据类型(大部分也支持Hive),这在通过HBase自身客户端查询Phoenix创建的表时,假如不是字符串型,会存在一定的转换乱码问题。
Phoenix支持UPSERT VALUES, UPSERT SELECT and DELETE的事务。
Secondary Indexes. Allow users to create indexes through a new CREATE INDEX DDL command, and then, behind the scenes, build multiple projections of the table (i.e. a copy of the table using re-ordered or different row key columns). Phoenix will take care of maintaining the indexes when DML commands are issued and will choose the best table to use at query time.
TopN Queries. Support a query that returns the top N rows, through support for derived tables and implementation of a server-side coprocessor that keeps the top N rows.
IN Optimizations. When an IN (or the equivalent OR) appears in a query using the leading row key columns, compile it into a batched get to more efficiently retrieve the query results.
COUNT DISTINCT. Although COUNT is currently supported, supporting COUNT DISTINCT will require returning more state to the client for the final merge operation.
CREATE SEQUENCE. Surface the HBase put-and-increment functionality through the standard SQL sequence support.
Dynamic Columns. For some use cases, it's difficult to model a schema up front. You may have columns that you'd like to specify only at query time. This is possible in HBase, in that every row (and column family) contains a map of values with keys that can be specified at run time. So, we'd like to support that.
Nested Children. Unlike with standard relational databases, HBase allows you the flexibility of dynamically creating as many key values in a row as you'd like. Phoenix could leverage this by providing a way to model child rows inside of a parent row. The child row would be comprised of the set of key values whose column qualifier is prefixed with a known name and appended with the primary key of the child row. Phoenix could hide all this complexity, and allow querying over the nested children through joining to the parent row.
Joins. Support hash joins first, where one side of the join is small enough to fit into memory.
Schema evolution. Phoenix supports adding and removing columns through the ALTER TABLE DDL command, but changing the data type of, or renaming, an existing column is not yet supported.
TABLESAMPLE. Implement a filter that uses a skip next hint based on the region boundaries of the table to only return n rows per region.
OLAP extensions. Support the WINDOW, PARTITION OVER, RANK, etc. functionality.