Apache Phoenix(一)答疑

  1. 我想开始使用Phoenix,如何编写Phoenix “Hello World”?
  2. Phoenix的JDBC URL语法格式?
  3. 如何批量加载数据至Phoenix?
  4. 如何映射Phoenix表至已有的Hbase表?
  5. 有哪些点关于Phoenix的优化的?
  6. 如何创建二级索引在表中?
  7. 为什么我的二级索引没被使用到?
  8. Phoenix速度多快?为什么这么快?
  9. 我如何更安全的连接Hbase集群?
  10. 我如何连接Hbase跑在Hadoop-2.x上?
  11. Phoenix可以像Hbase带有时间戳灵活的操作表吗?
  12. 我的查询为什么没有进入RANGE SCAN?
  13. 我应该创建Phoenix JDBC连接池吗?
  14. 为什么Phoenix在执行upsert时添加空键值或伪键值?

01. 我想开始使用Phoenix,如何编写Phoenix “Hello World”

  • 首先:下载最新版Phoenix来自apache phoenix下载页面,然后拷贝phoenix-*.jar放在Hbase lib的目录中,然后重启Hbase。

1. 命令行使用

  • 开始SQL命令行:
$ sqlline.py [zookeeper]
  • 在SQLline连接成功后执行如下语句:
> create table test (mykey integer not null primary key, mycolumn varchar);
> upsert into test values (1,'Hello');
> upsert into test values (2,'World!');
> select * from test;
+-------+------------+
| MYKEY |  MYCOLUMN  |
+-------+------------+
| 1     | Hello      |
| 2     | World!     |
+-------+------------+

2. JAVA语法

创建test.java 文件包含如下内容:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Statement;

public class test {

    public static void main(String[] args) throws SQLException {
        Statement stmt = null;
        ResultSet rset = null;
        
        Connection con = DriverManager.getConnection("jdbc:phoenix:[zookeeper]");
        stmt = con.createStatement();
        
        stmt.executeUpdate("create table test (mykey integer not null primary key, mycolumn varchar)");
        stmt.executeUpdate("upsert into test values (1,'Hello')");
        stmt.executeUpdate("upsert into test values (2,'World!')");
        con.commit();
        
        PreparedStatement statement = con.prepareStatement("select * from test");
        rset = statement.executeQuery();
        while (rset.next()) {
            System.out.println(rset.getString("mycolumn"));
        }
        statement.close();
        con.close();
    }
}

在命令行中编译和执行

$ javac test.java
$ java -cp "../phoenix-[version]-client.jar:." test
Hello World!

02. Phoenix的JDBC URL语法格式?

1. Thick Driver

Phoenix Thick驱动的JDBC的URL格式如下([]内的元素可选择的)

jdbc:phoenix:[comma-separated ZooKeeper Quorum [:port [:hbase root znode [:kerberos_principal [:path to kerberos keytab] ] ] ]

最简单的例子:

jdbc:phoenix:localhost

最复杂的例子:

jdbc:phoenix:zookeeper1.domain,zookeeper2.domain,zookeeper3.domain:2181:/hbase-1:phoenix@EXAMPLE.COM:/etc/security/keytabs/phoenix.keytab

请注意,URL中的每个可选元素都需要前面所有可选元素。例如,去指定Hbase的zk节点,那么zk的端口必须是指定的。
这些信息最初包含在该页

2. Thin Driver

Phoenix Thin驱动(与Phoenix查询服务一起使用)JDBC格式如下:

jdbc:phoenix:thin:[key=value[;key=value...]]

这里暴露了数个key供客户端使用。最经常使用的key为urlserialization。url key直接影响到需要查询的Phoenix查询服务器的地址。
最简单的URL例子:

jdbc:phoenix:thin:url=http://localhost:8765

非常复杂的URL例子:

jdbc:phoenix:thin:url=http://queryserver.domain:8765;serialization=PROTOBUF;authentication=SPENGO;principal=phoenix@EXAMPLE.COM;keytab=/etc/security/keytabs/phoenix.keytab

这里记录着所有有关于Thin 客户端JDBC URL涉及到的支持项,可以参考Apache Avatica documentationQuery Server Documentation

3. 如何批量加载数据至Phoenix?

1. Map Reduce

查看相关例子

2. CSV导入

CSV数据可以批量导入通过psql的通用功能。一般插入的速度在20K-50K行数据每秒。(取决于一行数据有多大)。
创建表例子:

 $ psql.py [zookeeper] ../examples/web_stat.sql

插入数据例子:

$ psql.py [zookeeper] ../examples/web_stat.csv

4. 如何映射Phoenix表至已有的Hbase表?

你可以创建Phoenix 表(table)和视图(view)通过 CREATE TABLE/CREATE VIEW 在已存在的HBase表上执行DLL语句。两种情况下都不会改变Hbase的元数据。对于CREATE TABLE,我们会创建任何不存在的元数据(table,column families)。我们会增加空键在每一行,所以查询的行为符合预期(不需要所有的列都进行扫描)。
需要注意的是字节的序列化必须匹配Phoenix的字节序列化。比如varchar、char和unsigned_类型,我们使用Hbase字节方法。char类型预期只有单字节字符和无符号类型预期值大于或者等于0。对于有符号的类型(tinyint,smallint,integer 和bigint),phoenix会翻转第一个字节,这样负值会在正值之前排序。因为Hbase排序row key按照ASCII正序排列,负值的第一位是1 而正值的第一位是0,那么负值大于正值,党我们不进行第一位翻转时。所以你存储整数时通过Hbase本地API接口和想通过Phoenix访问整数,确认你的数据类型是否是无符号类型。
我们复合row key可以将简单的值进行拼接在一起,在可变长类型上使用0字节作为分隔符。
如果你创建Hbase表如下:

create 't1', {NAME => 'f1', VERSIONS => 5}

如果你已经有了一张带有名称为't1'和列簇为'f1'的Hbase表。那么请记住,在Hbase中你不用对可能的键值和row key结构进行建模。这是你在phoenix指定的表和列簇之外的信息。所以在phoenix,你不需要像这样创建view:

CREATE VIEW "t1" ( pk VARCHAR PRIMARY KEY, "f1".val VARCHAR )

这个‘pk’列定义,你的row key是varchar类型(类似字符串),而'f1'.val列定义你的Hbase表包含键值形式和列成员及列限定符为'f1'.val还有他们的类型为varchar。
注意,你不需要使用双引号,当你创建你的hbase表包含所有的大写名称(Phoenix会标准化字符串,将字符串转大写)。比如:

create 'T1', {NAME => 'F1', VERSIONS => 5}

你可以这样创建phoenix视图:

CREATE VIEW t1 ( pk VARCHAR PRIMARY KEY, f1.val VARCHAR )

或者如果你创建了新的hbase表,不需要借助hbase shell,直接在phoenix操作。

CREATE TABLE t1 ( pk VARCHAR PRIMARY KEY, val VARCHAR )

5. 关于Phoenix的优化有哪些点?

  • 通过加盐(Salting)显著增加读写性能,通过预切割数据在多个regions。大多情况下加盐可以达到更好的性能效果。
    例子:
CREATE TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY, DESCRIPTION VARCHAR) SALT_BUCKETS=16

注意:理想情况下4核CPU的16个region server,可以选择salt buckets在32-64最佳性能。

  • 预切割表 的盐是自动进行表切割的,但是,如果希望精确地控制在不添加额外字节或更改row key顺序的情况下发生表拆分,则可以预先拆分一个表。
    例子:
CREATE TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY, DESCRIPTION VARCHAR) SPLIT ON ('CS','EU','NA')
  • 使用多个列簇
    列成员包含相关数据在相关的独立文件中。如果你的查询使用指定的列,将列分到一个列簇中,可以改善读性能。
    例子:
    使用DLL创建表并创建两个列簇A和B。
CREATE TABLE TEST (MYKEY VARCHAR NOT NULL PRIMARY KEY, A.COL1 VARCHAR, A.COL2 VARCHAR, B.COL3 VARCHAR)
  • 使用压缩在磁盘压缩上提升性能在大表上。
    例子:
CREATE TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY, DESCRIPTION VARCHAR) COMPRESSION='GZ'
  • 优化集群参数可以参考 这里
  • 优化Phoenix参数可以参考这里

6. 如何创建二级索引在表中?

始于Phoenix 2.1版本,Phoenix开始支持索引在可变和不可变的数据中。注意,Phoenix在2.0.x中仅支持不可变数据的索引。索引写性能在不可变索引表中,稍微快一些于可变数据表,不可变数据表即是数据不支持更新。
例子:

  • 创建表
不可变表: create table test (mykey varchar primary key, col1 varchar, col2 varchar) IMMUTABLE_ROWS=true;
可变表:create table test (mykey varchar primary key, col1 varchar, col2 varchar);
  • 创建索引在col2字段上
create index idx on test (col2);
  • 创建索引在col1中,并覆盖col2字段内容
create index idx on test (col1) include (col2);

更新行信息在test表中,Phoenix查询优化器会选择正确的索引去使用。你可以查看explain plan如果Phoenix使用这个索引表。你还可以在Phoenix查询中给出使用特定索引的提示

7. 为什么我的二级索引没被使用到?

除非查询中使用到的所有列都在二级索引中,否作不会使用二级索引(作为直接索引,或者覆盖索引)。构成数据表中的主键全部列都会自动包含在索引中。

DLL例子:
create table usertable (id varchar primary key, firstname varchar, lastname varchar); create index idx_name on usertable (firstname);
查询DLL:
select id, firstname, lastname from usertable where firstname = 'foo';

在lastname不是索引或者覆盖所有一部分时,索引是没有被使用到。这点可以在"explain plan"中被证实。在创建索引时固定lastname字段存在索引中一部分,或者时覆盖索引的覆盖字段。
例子:

create idx_name on usertable (firstname) include (lastname);

8.Phoenix速度有多快?为什么这么快?

Phoenix速度非常快,全表扫描100M的数据,通常情况下在20秒内完成(中等规模的集群上的小表)。如果查询包含到关键列的过滤器,则降低到毫秒级。你可以添加索引在导致性能等同于过滤键的列上,使用索引列作为键的一部分复制表。
为什么Phoenix即使做了全扫描,速度依然快:

  • Phoenix 将查询分块在region中,并且在查询的客户端上按照配置的线程数并行运行。
  • 聚合操作在服务器端的协程(coprocessor)上执行。折叠所有的数据返回给客户端而非全部返回数据。

9.我如何更安全的连接Hbase集群

检阅Anil Gupta的优秀文章

10. 我如何连接Hbase跑在Hadoop-2.x上?

Hadoop2的配置存在Phoenix的pom.xml中即可。

11. Phoenix可以像Hbase带有时间戳灵活的操作表吗?

在默认情况下,Phoenix让Hbase管理时间戳,并只让你查看最后的版本数据。但是,Phoenix也给用户提供支持任意的时间戳。要做到这一点,使用连接属性"CurrentSCN",像这样:

Properties props = new Properties();
props.setProperty("CurrentSCN", Long.toString(ts));
Connection conn = DriverManager.connect(myUrl, props);

conn.createStatement().execute("UPSERT INTO myTable VALUES ('a')");
conn.commit();

上面的操作等同于Hbase API中的:

myTable.put(Bytes.toBytes('a'),ts);

通过指定CurrentSCN,你可以告诉Phoenix。所有东西在这次连接中按该时间戳被完成。注意的是,这也适用于对连接执行的查询。举个例子,一个查询在myTable表的数据是不会看到刚插入的数据,因为它只看到创建连接时指定CurrentSCN属性之前的数据。这样提供了一种类似于快照的功能,或者是时间点查询。
请记住,创建个新的连接不是一个很昂贵的操作。相同的底层Hbase的连接用于全部连接的相同的集群,所以或多或少实例出一些对象。

12. 我的查询为什么没有进入RANGE SCAN?

DDL: CREATE TABLE TEST (pk1 char(1) not null, pk2 char(1) not null, pk3 char(1) not null, non-pk varchar CONSTRAINT PK PRIMARY KEY(pk1, pk2, pk3));

RANGE SCAN :意味着只扫描表中一部分数据。如果使用主键约束中的一个或者多个组成主键的列会出现这种情况。没有过滤PK列的查询,例子:select * from test where pk2='x' and pk3='y';将会出现全扫描,然而在select * from test where pk1='x' and pk2='y';中却是范围扫描(range scan)。注意,你可以添加二级索引在"pk2"和"pk3"列上,会触发范围扫描(range scan)在第一次查询中。
DEGENERATE SCAN:意味着一个查询不能返回行数据。如果我们决定在编译时完成。我们甚至不需要运行扫描。
FULL SCAN:意味着所有行都被扫描到。(如果你有一个where子句,可能会应用到一个过滤器)
SKIP SCAN:将扫描一个表中的子集或者全部行。无论如何它将会根据过滤器跳过大分组的行。可以查看博客了解更多。如果主键上没有过滤器的列,那我们就不做SKIP SCAN,但是你可以强制SKIP SCAN通过使用/+ SKIP_SCAN/去命中。在一些条件下,也就是说当你的主键基数比较少时,它将会更有效超过FULL SCAN。

13. 我应该创建Phoenix JDBC连接池吗?

不,它不是必须的Phoenix jDBC连接池。
Phoenix的连接对象时不同大部分的JDBC连接,原因在于底层是Hbase的连接。Phoenix连接对象在设计时就是为了更精细便宜的代价去创建。如果Phoenix的连接被再利用,底层的HBase连接可能并不总是由前一个用户保持在健康状态。更好的方式是去创建一个新的Phoenix连接,保证避免潜在的问题。
实行Phoenix连接池可以简单的创建实例化委派,对外部而言,创建出新的Phoenix连接,实际是需要时从池中获取,对外部而言的关闭,实际是返回到池中去,可以参考Phoenix-2388

14. 为什么Phoenix在执行upsert时添加空键值或伪键值?

空键值或者伪键值(_01列限定符)必须的,去保证列都有有效的在全部行中。
数据存储在Hbase是以键值对形式存在,意味着存储每个列值完整的行键。这还意味着,除非至少存储了一个列,否则根本不存储行键。
现在考虑到JDBC的行存在int类型的主键,和若干列可能是空(null)的。为了可以存储主键,键值必须去存储去展示这行数据的全部(现在的时间戳,考虑的时间戳版本)。你会注意到这些列是空列。这允许执行“SELECT * FROM TABLE”并接收所有行的记录,即使那些非pk列为空的记录也是如此。
即使对于某些(或所有)记录只有一个列为空,也会出现相同的问题。在Phoenix上的扫描将包括空列,以确保只包含主键的行(所有非键列都为空)将包含在扫描结果中。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容