apache-phoenix F.A.Q翻译

这做段时间在学习phoenix,这是一个sql-on-hbase的工具,提供了对hbase sql的支持,也添加了二级缓存等一些特性。我个人感觉一个好的学习方式就是去看他的官方文档,也就顺便翻译了一下当作自己的学习笔记,由于个人英语能力和也是刚接触phoenix,难免有疏漏之处,错误之处请大家多多指正。也在这儿给出源地址http://phoenix.apache.org/faq.html

Q:我想要开始使用phoenix,有没有phoenix版的HelloWorld

A: 需要准备:在这儿下载最新版本的phoenix,复制phoenix-*.jar到hbase的lib文件夹中,并重启hbase
- 使用控制台

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!     | 
+-------+------------+
  • 使用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();
    }
}

在命令行中编译并执行
注,手动引jar包,需要自己添加Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");把phoenix驱动引入到classpath中。

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

你就会得到下面的结果:

Hello World!
Q:有没有在phoenix大规模加载数据的方法

A:
MapReduce
示例:点我
CSV
csv数据能用psql进行大量加载,通常一秒能够upsert20k-50k行(根据行有多宽决定)

用法示例:
使用psql创建表:$ psql.py [zookeeper] ../examples/web_stat.sql
插入csv数据:$ psql.py [zookeeper] ../examples/web_stat.csv

我怎么映射一个已经存在的hbase表到phoenix表

A: 你可以使用CREATE TABLE/CREATE VIEW DDL 块在一个已经存在的hbase表上创建一张表或一个视图(view),在这两种情况下,我们会保留hbase的元数据,除非你设置KEEP_DELETED_CELLS 为on。对于Create Table 我们会创建一切没有的元数据(包括表,列族)。我们还将为每行添加一个空的值,以便查询预期的行为(在扫描过程中不需要检查所有列)
另外一个说明就是,bytes序列化的方式必须匹配Phoenix的方式。对于VARCHER, CHAR和UNSIGNED_*的类型,我们会使用hbase的Bytes方法。 CHAR 类型只能是一个字节,而且UNSIGNED 的类型是大于或者等于0.
我们的复合rowkey是简单的使用0为分隔符把value连接到一块(after a variable length type)一零字节的字符作为一个可变长度的类型后分离器。。
如果你创建一个这样的Hbase表:

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

这样你就会有一个名为tl, 列族名为’f1’的hbase表。请记住,在hbase中, Remember, in HBase, you don’t model the possible KeyValues or the structure of the row key,这是你需要在表和列族中指定的信息。
所以,在phoenix中,你能够这样创建一个视图:

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

pk的列声明你的rowkey是一个Varchar(String)类型的, “f1”.val 列 表明你的hbase表包含一个“f1:val”的列,并且这个列的值是String类型的。
注意,当你使用大写字母创建你的hbase表的时候,你不需要使用双引号(因为这是phoenix是通过把string转化大写来规范字符串)。例如:

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

你可以这样来创建phoenix视图:

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

或者你要创建一个新的hbase表,只要让phoenix做你喜欢的任何事情,没有必要再使用Hbase Shell了。

CREATE TABLE t1 ( pk VARCHAR PRIMARY KEY, val VARCHAR )
Q:有没有一些优化phoenix的tips

A:
- 使用Salting 来提高读写的效率,Salting 能够显著提高已经分裂成多个区域的数据的性能。但是Salting 只是会在大多数情况下更好的性能。
例如:

CREATE TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY, DESCRIPTION VARCHAR) SALT_BUCKETS=16

注意:四核cpu,16个regionServer的集群,选择32-64个* salt buckets*会有最理想的优化表现

  • Per-split table Salting表 不会自动的分裂,但是如果你想完全控制表的分裂。增加额外的字节或者更改row key的顺序就可以预分裂一张表
    例如:
CREATE TABLE TEST (HOST VARCHAR NOT NULL PRIMARY KEY, DESCRIPTION VARCHAR) SPLIT ON ('CS','EU','NA')
  • 使用多个列族
    列族在多个分割的文件中存储了有关系的数据。如果你查询一些指定的列,那你可以把这些列放到一个列族中以提高读的性能
Q:我怎么在一张表上创建二级索引

A:以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上创建索引,并联合(covered )col2中的索引
create index idx on test (col1) include (col2)

在test表中Upset行,phoenix会使用正确的索引来优化查询。如果phoenix正在使用索引表来查询数据,你可以查看执行计划,你也可以使用hint来指定一个index

为什么我的二级索引没有作用

A:
只有在查询的所有列都有索引的时候,二级才会正常工作(包括indexed或者covered列),查询所有列的话,所有列会组成表的主键,会自动包含在索引中。
例如:
DDL:

create table usertable (id varchar primary key, firstname varchar, lastname varchar); create index idx_name on usertable (firstname);

查询sql:

select id, firstname, lastname from usertable where firstname = 'foo';

在这个例子中将不会使用索引,因为lastname不是索引列,也不是联合索引。你可以查看一个执行计划来确认这一点,想要修正这个问题,只要在lastname上创建一个索引或者一个联合索引就可以了,例如:

create idx_name on usertable (firstname) include (lastname);
Q:phoeniex有多快,它为什么这么快

phoeniex很快,一个1亿行的全表扫描通常会在20s以内完成(一个中等集群的窄表)。如果查询中包含了key column, 这个时间会缩短到几毫秒,对于不是key column或者leading key column的,您可以在这些列中添加索引,该索引将能够让性能相当于通过使用索引列的表的一部分来对关键列进行筛选的性能。
为什么甚至在full scan时性能也这么高

  1. phoenix块使用该region的边界,并在客户端使用一个可配置的线程并行运行的查询
  2. 聚合将在服务器端一个协处理器完成,数据量会在collapsing 会返回,而不是直接返回
Q:phoenix可以在像flexible 或者HBase API那样访问任意时间戳的表吗?

A:默认设置是,phoenix让Hbase管理timestamps ,并且只返回你最后的数据,然而,phoenix也支持用户提供的任意时间戳。想使用这个功能,你在连接的时候必须指定一个“CurrentSCN”(或者PhoenixRuntime.CURRENT_SCN_ATTRIB),例如:

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

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

上面相当于hbaseApi的

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

通过指定CurrentSCN,你能告诉phoenix你在这个指定的时间戳想做的一切。请注意,在连接上使用CurrentSCN,也对查询有效,例如,在mytalbe中查询不会看到刚刚upsert的数据,只能看到CurrentSCN 属性之前插入的数据。这样就提供了一个使用快照(snapshot),闪回(flashback),和一个时间点(point-in-time)的查询
请记住:创建一个新的连接不是一个特别费时的操作,对于一个集群,phoenix只会使用一个HConnection, 所以一个phoenix连接只是几个对象的实例化而已。

Q:为什么我的查询没有使用范围扫描

A: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));

范围扫描指的是只会扫描你的表的一个子集。当你使用一个或者多个pk约束的 leading columns时,就会使用范围扫描。当查询的列不在pk列的前面时:例:select * from test where pk2='x' and pk3='y',就会使用全表扫描。而select * from test where pk1='x' and pk2='y';会使用范围扫描。需要注意的是在select * from test where pk2='x' and pk3='y'上可以添加二级索引,就会改成范围扫描(在索引表上)

DEGENERATE SCAN意味着不会返回任何数据,如果你能在编译期就能决定,我们甚至都不会费时去扫描。

FULL SCAN 意味着所有的行都会被扫描

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值