Phoenix
1.Phoenix定义
Phoenix是构建在HBase上的一个SQL层,能让我们用标准的JDBC APIs而不是HBase客户端APIs来创建表,插入数据和对HBase数据进行查询。
Phoenix完全使用Java编写,作为HBase内嵌的JDBC驱动。Phoenix查询引擎会将SQL查询转换为一个或多个HBase扫描,并编排执行以生成标准的JDBC结果集。直接使用HBase API、协同处理器与自定义过滤器,对于简单查询来说,其性能量级是毫秒,对于百万级别的行数来说,其性能量级是秒。
HBase的查询工具有很多,如:Hive、Tez、Impala、Spark SQL、Phoenix等。
hoenix通过以下方式使我们可以少写代码,并且性能比我们自己写代码更好:
- 将SQL编译成原生的HBase scans。
- 确定scan关键字的最佳开始和结束
- 让scan并行执行
2.Secondary Indexing 二级索引
在HBase中,只有一个单一的按照字典序排序的rowKey索引,当使用rowKey来进行数据查询的时候速度较快,但是如果不使用rowKey来查询的话就会使用filter来对全表进行扫描,很大程度上降低了检索性能。而Phoenix提供了二级索引技术来应对这种使用rowKey之外的条件进行检索的场景。
- Covered Indexes
只需要通过索引就能返回所要查询的数据,所以索引的列必须包含所需查询的列(SELECT的列和WHRER的列)
- Functional Indexes
从Phoeinx4.3以上就支持函数索引,其索引不局限于列,可以合适任意的表达式来创建索引,当在查询时用到了这些表达式时就直接返回表达式结果.
- Global Indexes
Global indexing适用于多读少写的业务场景。
使用Global indexing的话在写数据的时候会消耗大量开销,因为所有对数据表的更新操作(DELETE, UPSERT VALUES and UPSERT SELECT),会引起索引表的更新,而索引表是分布在不同的数据节点上的,跨节点的数据传输带来了较大的性能消耗。在读数据的时候Phoenix会选择索引表来降低查询消耗的时间。在默认情况下如果想查询的字段不是索引字段的话索引表不会被使用,也就是说不会带来查询速度的提升。
- Local Indexes
Local indexing适用于写操作频繁的场景。
与Global indexing一样,Phoenix会自动判定在进行查询的时候是否使用索引。使用Local indexing时,索引数据和数据表的数据是存放在相同的服务器中的避免了在写操作的时候往不同服务器的索引表中写索引带来的额外开销。使用Local indexing的时候即使查询的字段不是索引字段索引表也会被使用,这会带来查询速度的提升,这点跟Global indexing不同。一个数据表的所有索引数据都存储在一个单一的独立的可共享的表中。
3.Statistics Collection 统计信息收集
UPDATE STATISTICS可以更新某张表的统计信息,以提高查询性能
4.Row timestamp 时间戳
Phoenix提供了一种将HBase原生的row timestamp映射到Phoenix列的方法。这样有利于充分利用HBase提供的针对存储文件的时间范围的各种优化,以及Phoenix内置的各种查询优化。
5.Paged Queries 分页查询
Phoenix支持分页查询:
- Row Value Constructors (RVC)
- OFFSET with limit
6.数据存储
Phoenix将HBase的数据模型映射到关系型世界
7.对SQL的支持
- SELECT
Example:
SELECT * FROM TEST LIMIT 1000;
SELECT * FROM TEST LIMIT 1000 OFFSET 100;
SELECT full_name FROM SALES_PERSON WHERE ranking >= 5.0 UNION ALL SELECT reviewer_name FROM CUSTOMER_REVIEW WHERE score >= 8.0
- UPSERT VALUES
Example:
UPSERT INTO TEST VALUES('foo','bar',3);
UPSERT INTO TEST(NAME,ID) VALUES('foo',123);
- UPSERT SELECT
Example:
UPSERT INTO test.targetTable(col1, col2) SELECT col3, col4 FROM test.sourceTable WHERE col5 < 100
UPSERT INTO foo SELECT * FROM bar;
- DELETE
Example:
DELETE FROM TEST;
DELETE FROM TEST WHERE ID=123;
DELETE FROM TEST WHERE NAME LIKE 'foo%';
- CREATE TABLE
CREATE TABLE my_schema.my_table ( id BIGINT not null primary key, date)
CREATE TABLE my_table ( id INTEGER not null primary key desc, date DATE not null,m.db_utilization DECIMAL, i.db_utilization) m.DATA_BLOCK_ENCODING='DIFF'
CREATE TABLE stats.prod_metrics ( host char(50) not null, created_date date not null,txn_count bigint CONSTRAINT pk PRIMARY KEY (host, created_date) )
CREATE TABLE IF NOT EXISTS "my_case_sensitive_table"
( "id" char(10) not null primary key, "value" integer)
DATA_BLOCK_ENCODING='NONE',VERSIONS=5,MAX_FILESIZE=2000000 split on (?, ?, ?)
CREATE TABLE IF NOT EXISTS my_schema.my_table (org_id CHAR(15), entity_id CHAR(15), payload binary(1000),CONSTRAINT pk PRIMARY KEY (org_id, entity_id) )TTL=86400
- DROP TABLE
Example:
CREATE FUNCTION my_reverse(varchar) returns varchar as 'com.mypackage.MyReverseFunction' using jar 'hdfs:/localhost:8080/hbase/lib/myjar.jar'
CREATE FUNCTION my_reverse(varchar) returns varchar as 'com.mypackage.MyReverseFunction'
CREATE FUNCTION my_increment(integer, integer constant defaultvalue='10') returns integer as 'com.mypackage.MyIncrementFunction' using jar '/hbase/lib/myincrement.jar'
CREATE TEMPORARY FUNCTION my_reverse(varchar) returns varchar as 'com.mypackage.MyReverseFunction' using jar 'hdfs:/localhost:8080/hbase/lib/myjar.jar'
- CREATE VIEW
Example:
CREATE VIEW "my_hbase_table"( k VARCHAR primary key, "v" UNSIGNED_LONG) default_column_family='a';
CREATE VIEW my_view ( new_col SMALLINT ) AS SELECT * FROM my_table WHERE k = 100;
CREATE VIEW my_view_on_view AS SELECT * FROM my_view WHERE new_col > 70;
- DROP VIEW
Example:
DROP VIEW my_view
DROP VIEW IF EXISTS my_schema.my_view
DROP VIEW IF EXISTS my_schema.my_view CASCADE
- CREATE SEQUENCE
Example:
CREATE SEQUENCE my_sequence;
CREATE SEQUENCE my_sequence START WITH -1000
CREATE SEQUENCE my_sequence INCREMENT BY 10
CREATE SEQUENCE my_schema.my_sequence START 0 CACHE 10
- DROP SEQUENCE
Example:
DROP SEQUENCE my_sequence
DROP SEQUENCE IF EXISTS my_schema.my_sequence
- ALTER
Example:
ALTER TABLE my_schema.my_table ADD d.dept_id char(10) VERSIONS=10
ALTER TABLE my_table ADD dept_name char(50), parent_id char(15) null primary key
ALTER TABLE my_table DROP COLUMN d.dept_id, parent_id;
ALTER VIEW my_view DROP COLUMN new_col;
ALTER TABLE my_table SET IMMUTABLE_ROWS=true,DISABLE_WAL=true;
- CREATE INDEX
Example:
CREATE INDEX my_idx ON sales.opportunity(last_updated_date DESC)
CREATE INDEX my_idx ON log.event(created_date DESC) INCLUDE (name, payload) SALT_BUCKETS=10
CREATE INDEX IF NOT EXISTS my_comp_idx ON server_metrics ( gc_time DESC, created_date DESC ) DATA_BLOCK_ENCODING='NONE',VERSIONS=?,MAX_FILESIZE=2000000 split on (?, ?, ?)
CREATE INDEX my_idx ON sales.opportunity(UPPER(contact_name))
- DROP INDEX
Example:
DROP INDEX my_idx ON sales.opportunity
DROP INDEX IF EXISTS my_idx ON server_metrics
- ALTER INDEX
Example:
ALTER INDEX my_idx ON sales.opportunity DISABLE
ALTER INDEX IF EXISTS my_idx ON server_metrics REBUILD
- EXPLAIN
Example:
EXPLAIN SELECT NAME, COUNT(*) FROM TEST GROUP BY NAME HAVING COUNT(*) > 2;
EXPLAIN SELECT entity_id FROM CORE.CUSTOM_ENTITY_DATA WHERE organization_id='00D300000000XHP' AND SUBSTR(entity_id,1,3) = '002' AND created_date < CURRENT_DATE()-1;
- UPDATE STATISTICS
Example:
UPDATE STATISTICS my_table
UPDATE STATISTICS my_schema.my_table INDEX
UPDATE STATISTICS my_index
UPDATE STATISTICS my_table COLUMNS
UPDATE STATISTICS my_table SET phoenix.stats.guidepost.width=50000000
- CREATE SCHEMA
Example:
CREATE SCHEMA IF NOT EXISTS my_schema
CREATE SCHEMA my_schema
- USE
Example:
USE my_schema
USE DEFAULT
- DROP SCHEMA
Example:
DROP SCHEMA IF EXISTS my_schema
DROP SCHEMA my_schema
8.内置函数
支持的聚合函数有:
Ø 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
9.Phoenix表操作
9.1 创建表
CREATE TABLE IF NOT EXISTS us_population (
state CHAR(2) NOT NULL,
city VARCHAR NOT NULL,
population BIGINT
CONSTRAINT my_pk PRIMARY KEY (state, city));
UPSERT INTO us_population (state, city, population) values ('NY','New York',8143197);
UPSERT INTO us_population (state, city, population) values ('CA','Los Angeles',3844829);
在phoenix中,默认情况下,表名等会自动转换为大写,若要小写,使用双引号,如"us_population"。
9.2 显示所有表
!tables