Phoenix是基于HBase的SQL中间件产品,由Salesforce.com公司开源并托管于Github上。对于熟悉关系型数据库的开发人员来说,通过Phoenix可以像使用MySQL等关系型数据库一样使用HBase中的数据表。值得注意的是,它还提供了JDBC驱动包供Java程序访问数据。在实现时,充分利用了HBase协处理器和过滤器等底层
首先需要安装好HBase集群,且采用的版本在0.94.4以上,JDK版本1.6以上。本文采用的phoenix版本为phoenix-2.0.1(http://phoenix-bin.github.com/client/phoenix-2.0.1-install.tar),所以如果有相关差异或更改,请以官方公布文档为准。
安装phoenix非常简单,从下载的tar包中取出phoenix-2.0.1.jar,将其放入HBase集群中所有RS节点安装目录lib中,同时记得移除之前安装的phoenix老版本,如果安装过的话。然后重启所有RS节点服务。如果采用Java代码访问,请采用与之匹配的client版本,比如本文的phoenix-2.0.1-client.jar。
为便于测试,可将下载的包内容放置到HBase集群某个节点机器上,比如本文将其放置到HMaster机器vnode120的$HBASE_HOME phoenix中,为检验phoenix是否安装成功,请进入$HBASE_HOME/phoenix/bin目录,并赋予所有*.sh可执行权限,操作如下:
sqlline.sh为其提供的命令行工具,可以在其中执行建表,查询等相关动作。运行该脚本需要跟zk参数,vnode121为某个zk节点。连上后,执行!tables会列出所有通过phoenix建的表,其中SYSTEM.TABLE这张表默认会存在,其中存放phoenix实现中的数据类型映射等信息。当能执行这些操作后,说明phoenix功能已经正常整合进现有HBase集群中,您接下来就可以体验HBase之上执行SQL功能的奇妙之旅了。
1)create:可以创建一张表或视图。表名如果没有用双引号括起来,默认都会使用其对应的大写字母名字表示,括起来后跟括起来的值保持一致。如果创建的表已经存在,且其不是通过phoenix create语法创建的,则可以继续使用phoenix create创建同名表,不影响原有表数据,但会影响通过phoenix select结果值存在部分不需要的值。创建视图时,需要对应的表和列族已存在,不能对表中数据进行更新操作。建表语句中,还可以附加一些HBase表、列族配置选项,如VERSIONS、MAX_FILESIZE etc.
CREATETABLE IF NOT EXISTS my_table ( id char(10) not null primary key, value integer);
CREATETABLE IF NOT EXISTS my_schema.my_table ( id char(10) not null primary key,value integer) DATA_BLOCK_ENCODING='NONE',VERSIONS=10,MAX_FILESIZE=20480;
2)alter:可添加或删除一列或更新表属性。被移除的列,其上数据会被删除。如果该列是主键,不能被移除,如果移除列的是一个视图,数据是不会受影响的。
ALTERTABLE my_table ADD dept_name varchar(50)
ALTERTABLE my_table DROP COLUMN parent_id
ALTERTABLE my_table SET IMMUTABLE_ROWS=true
3)drop:删除表或视图。如果删除表,表中数据也会被删除,如果是视图则不受影响。
DROPTABLE my_schema.my_table
DROP VIEW my_view
4)upsert:更新或插入数据。如果表中不存在该数据则插入,否则更新,所以可以看出phoenix没有单独定义insert 或update命令。列列表可以省略,但后面插入的值顺序需要与表schema定义顺序保持一致,也可自己定义插入哪些column对应值,顺序与之对应即可。目前还支持一种选择性upsert的方式,它将另外一个查询的结果作为值插入表中。如果auto commit开启的话,会在服务端就提交了,否则会缓存到客户端,等着显式提交的时候进行批量upsert,通过配置” phoenix.mutate.upsertBatchSize”指定大小,默认10000行/次。
UPSERTINTO TEST VALUES('foo','bar',3);
UPSERTINTO TEST(NAME,ID) VALUES('foo',123)
5)delete:删除指定行。如果auto commit开启,则会直接在服务端执行删除。
DELETE FROM TEST;
DELETE FROM TEST WHERE ID=123;
6)index:二级索引。在表或视图上创建二级索引,当前版本仅支持对具有IMMUTABLE_ROWS属性的表上添加二级索引。目前实现是在数据行插入后便插入了索引。当创建了索引后,其实也会在HBase中创建一张表,表名为该二级索引名,所以还可对该index指定创建表相关参数。同时还可删除索引和修改索引。
CREATEINDEX my_idx ON sales.opportunity(last_updated_date DESC)
DROPINDEX my_idx ON sales.opportunity
ALTERINDEX my_idx ON sales.opportunity DISABLE
7)explain:执行计划。提供一个很简单的方式查看执行给定命令所需的逻辑步骤。每个步骤局势以单行字符串进行输出表示。这个可以很容易定位查询的性能瓶颈,或者所建二级索引是否生效等。
explain select * from test where age>0;
8)其他
constraint定义主键约束,默认按照列升序排列:
CONSTRAINTmy_pk PRIMARY KEY (host,created_date)
选项,如之前用到的IMMUTABLE_ROWS=true,默认设置了这个选项的表才允许建索引。Phoenix默认是修改HBase元数据来使之生效,适用于HColumnDescriptor和HTableDescriptor相关选项。值得一提的是SALT_BUCKETS选项,它为每个rowkey预置一个字节,使其分布在不同rs上来避免写热点rs。
IMMUTABLE_ROWS=true
SALT_BUCKETS=10
hint,可重置默认的查询行为。一般用于sql调优。目前支持SKIP_SCAN,RANGE_SCAN,NO_INTRA_REGION_PARALLELIZATION,NO_INDEX,INDEX5个hint。
select /*+NO_INDEX */* from test where age>0
建表,建索引或alter等操作的时候,名称都可以用.分隔,如果是表,则前部分为schema名(默认null),如果是column,则前部分是family名(默认’_0’)。不用双引号括起来的时候为大小写不敏感的。
选择表达式可以用*和
为表定义分割点,可以使用preparedStatement.setBinary(int,byte[])提供任意字节的分割。
目前不支持join和子查询,可以为表和列定义别名,方法是使用as或直接将别名跟在真名后面。
目前查询支持排序,比如按照某列升序,降序等。ORDER BY NAME ASC NULLSLAST。
支持的关系连接符有AND和OR。如果使用LIKE,可以用通配符_(单个字符)和%(任意字符)。若查询的字符串本身就包括则需要对其转义(\)。Between是个闭区间[5,10]
比较运算符有<>,<=,>=,=,<,>,!=其中<>与!=等效。字符串连接可以用||,数字和日期类型可以做+,-,*,/。
支持的聚合函数有:
Ø AVG:求平均,如果没有返回NULL
Ø SUM:
Ø COUNT:求行数,如果指定某列,则返回该列非空个数,如果为*或1,则返回所有行,加上distinct则返回不相同的行数
Ø MAX:求最大值
Ø MIN:求最小值
Ø PERCENTILE_CONT:指定??
Ø PERCENTILE_DISC:指定占比的列具体值是多少
Ø PERCENT_RANK:指定值占的百分比,PERCENT_RANK( 39 ) WITHINGROUP (ORDER BY id ASC)
Ø STDDEV_SAMP:样本标准差
Ø STDDEV_POP:总体标准差
支持的字符串函数:
Ø SUBSTR:取子串,默认是基于1的,如果想基于0,则指定0,如果指定为负数,则是从字符串结尾算起
Ø TRIM:去除字符串头尾空格
Ø LTRIM:去除字符串左侧空格
Ø RTRIM:去除字符串右侧空格
Ø LENGTH:返回字符串长度
Ø REGEXP_SUBSTR:通过指定正则表达式获取子串
Ø REGEXP_REPLACE:正则替换
Ø UPPER:大写转换
Ø LOWER:小写转换
Ø REVERSE:字符串反转
Ø TO_CHAR:将日期、时间、时间戳或数字格式化为一个字符串。默认日期格式为yyyy-MM-dd HH:mm:ss,数字格式为#,##0.###。
支持的时间、日期函数:
Ø ROUND:四舍五入?
Ø TRUNC:截断
Ø TO_DATE:转换为date类型
Ø CURRENT_DATE:返回RS上当前日期
Ø CURRENT_TIME:返回RS上当前时间
支持的时间、日期函数:
Ø TO_NUMBER:转换日期、时间、时间戳为一个数字,可接受格式化串?
Ø COALESCE:指定默认值,如果相应值为null
Ø INTEGER:范围为-2147483648 到 2147483647,与java.lang.Integer映射。但注意的是其二进制表示需要其会把第一个符号位进行翻转,这样保证负数排列在正数前面。
Ø UNSIGNED_INT:范围为0到2147483647,这个是与java.lang.Integer对应,其二进制呈现形式和Bytes.toBytes(int)方法产生的一致。
Ø BIGINT:范围为-9223372036854775808 到9223372036854775807 ,与java.lang.Long对应。8个字节,同时也是符号位反转。
Ø UNSIGNED_LONG:可能值为0到9223372036854775807 ,与Bytes.toBytes(long)对应。
Ø TINYINT:-128到127。与java.lang.Byte对应。符号位也需要反转。
Ø UNSIGNED_TINYINT:0到127。二进制表示形式就是一个单字节,和Bytes.toBytes(byte)对应。
Ø SMALLINT:-32768到32767。与java.lang.Short对应。符号位需要反转。
Ø UNSIGNED_SMALLINT:0到32767。二进制表示形式与Bytes.toBytes(short)对应。
Ø FLOAT: -3.402823466 E + 38 到 3.402823466 E + 38,与java.lang.Float对应,首字节需要反转。
Ø UNSIGNED_FLOAT: 0 到 3.402823466 E + 38,二进制表示形式与Bytes.toBytes(float)一致。
Ø DOUBLE:范围为-1.7976931348623158 E + 308 到 1.7976931348623158 E + 308。与java.lang.Double对应,二进制形式首位需反转。
Ø UNSIGNED_DOUBLE: 0到1.7976931348623158 E + 308。二进制表示形式与Bytes.toBytes(double)对应。
Ø DECIMAL:具有固定精度。最大精度为18位,与java.math.BigDecimal对应。其二进制表示形式为可变长度格式。当用于rowkey中,其后会产生一个nullbyte,除非它是最后一列。
Ø BOOLEAN:二进制形式0表示false,1表示true
Ø TIME:格式为yyyy-MM-DD hh:mm:ss,具有日期和时间两部分。与java.sql.Time对应。二进制表示形式为8个字节的long型,代表从EPOCH开始的毫秒数
Ø DATE: 格式为yyyy-MM-DD hh:mm:ss,具有日期和时间两部分。与java.sql.DATE对应。二进制表示形式为8个字节的long型,代表从EPOCH开始的毫秒数。
Ø TIMESTAMP:格式为yyyy-MM-dd hh:mm:ss[.nnnnnnnnn],与java.sql.Timestamp,二进制表示为12个字节,8个字节表示long毫秒数,4个字节表示int纳秒数
Ø VARCHAR:具有最大字节长度(可选)的可变长字符串。当用于rowkey时,会在末尾加一个null字节,而如果它正好位于rowkey最后部分则不加。
Ø CHAR:固定长度字符串。二进制表示是UTF8形式与Bytes.toBytes(string)对应。
Ø BINARY:原始固定长度二进制字节数组,与byte[]对应
Ø VARBINARY:原始可变长度二进制格式字节数组。
HBase 官方:https://hbase.apache.org/
Phoenix 官方:https://github.com/forcedotcom/phoenix