Phoenix四贴之一:扫盲贴

摘要: Phoenix扫盲贴

1 简介Introduction

Apache Phoenix is a relational database layer over HBase delivered as a client-embedded JDBC driver targeting low latency queries over HBase data. Apache Phoenix takes your SQL versioned, such that snapshot queries over prior versions will automatically use the correct performance on the order of milliseconds for small queries, or seconds for tens of millions of rows. 


Apache Phoenix是构建在HBase之上的关系型数据库层,作为内嵌的客户端JDBC驱动用以对HBase中的数据进行低延迟访问。Apache Phoenix会将用户编写的sql查询编译为一系列的scan操作,最终产生通用的JDBC结果集返回给客户端。数据表的元数据存储在HBase的表中被会标记版本号,所以进行查询的时候会自动选择正确的schema。直接使用HBase的API,结合协处理器(coprocessor)和自定义的过滤器的话,小范围的查询在毫秒级响应,千万数据的话响应速度为秒级。

1.1 Phoenix在Hadoop生态系统中的位置

Phoenix在Hadoop生态系统中的位置

1.2 Phoenix官网

http://phoenix.apache.org/

2 安装说明

本篇主要介绍Phoenix的安装部署。

2.1 系统环境

如下:

Centos-6.4 (64-bit)
Jdk-1.7.0_75
Hadoop-2.5.0-cdh5.2.0
Zookeeper-3.4.5-cdh5.2.0
Hbase-0.98.6-cdh5.2.0
Solr-4.4.0-cdh5.2.0
Hbase-solr-1.5-cdh5.2.0
Sqoop-1.4.5-cdh5.2.0
Sqoop2-1.99.3-cdh5.2.0
Hive-0.13.1-cdh5.2.0
Flume-ng-1.5.0-cdh5.2.0

2.2 下载

从官网下载安装包

http://phoenix.apache.org/download.html

这里需要注意不同版本的phoenix与HBase的兼容性

这里写图片描述

我目前使用的HBase版本为hbase-0.98.6-cdh5.2.0,因此下载phoenix4.x的

http://apache.fayea.com/phoenix/

上面的下载地址是镜像地址,如果不可用的话可以从下载选择其他镜像地址

http://www.apache.org/dyn/closer.cgi/incubator/phoenix/

这里写图片描述

2.3 安装

安装过程参考官网链接

http://phoenix.apache.org/installation.html

2.3.1 上传部署

将phoenix-4.2.2-bin.tar.gz上传到服务器解压重命名为phoenix-4.2.2,【PHOENIX_HOME】为【/usr/local/cdh-5.2.0/phoenix-4.2.2】

这里写图片描述

2.3.2 拷贝jar包

将【PHOENIX_HOME】目录下的phoenix-[version]-server.jar添加到HBase集群的所有regionserver节点的lib目录下(use phoenix-core-[version].jar for Phoenix 3.x),然后重启HBase集群。

2.3.3 连接HBase

进入【PHOENIX_HOME/bin】目录下启动客户端进入CLI界面,执行如下命令连接HBase集群。

$ ./sqlline.py 192.168.187.128,192.168.187.129,192.168.187.130:2181

 高能预警:这里的192.168.187.128,192.168.187.129,192.168.187.130参数是HBase集群zookeeper集群的ip地址,2181是zookeeper端口号。

这里写图片描述

查看当前所有表

> !tables

这里写图片描述

高能预警:CATALOG、SEQUENCE、STATS这三张表是系统自带的表。HBase中已存在的表不会自动映射过来,需要手动创建相同结果的数据表,具体过程后面会说到。

从HBase的CLI界面查看是否同样多出这三张表

> list

这里写图片描述

安装成功。

3 CLI CRUD操作

3.1 说明

本篇主要介绍在phoenix的CLI中进行简单的CRUD操作。phoenix中支持的命令如下:

这里写图片描述

详细的命令语法参考官网说明

http://phoenix.apache.org/language/index.html

3.2  CURD

在CLI中进行创建表、插入数据、查询数据、更新数据、删除数据、删除表的操作。

3.2.1 创建表

创建user数据表

> CREATE TABLE user (id varchar PRIMARY KEY,account varchar ,passwd varchar);

 高能预警:Phoenix会自动将表名和字段名转换为大写字母,如果不想转换的话可以使用双引号括起来

进入HBase的CLI界面查看user表是否被创建成功

> list

这里写图片描述

查看USER表结构

> describe 'USER'

这里写图片描述

从上图得知,默认列族为0,id主键字段对应到hbase的ROW字段。

高能预警:如果想指定列族与列的话使用如下语句建表

> CREATE TABLE user (id varchar PRIMARY KEY,INFO.account varchar ,INFO.passwd varchar);

这里写图片描述

3.2.2 插入数据

插入数据到user表中,这里的命令与RDBMS中插入数据语法稍有差别。upsert

> upsert into user(id, account, passwd) values('001', 'admin', 'admin');

3.2.3 查询数据

查询user表中数据

select * from user;

3.2.4 更新数据

更新数据的语法与插入数据相同。

> upsert into user(id, account, passwd) values('001', 'admin', 'dimensoft');

3.2.5 删除数据

删除id为001的数据

> delete from user where id='001';

3.2.6 删除表

删除user数据表

drop table user;

 以上就是在phoenix的CLI界面中进行简单的CRUD操作,基本上与RDBMS的操作没有太大区别,上手也比较容易。

4 JDBC操作

4.1 说明

本部分主要介绍使用JDBC的方式来对HBase中的数据进行CRUD操作,项目为maven项目。请自行将phoenix-4.2.2-client.jar(可以在下载的phoenix-4.2.2-bin.tar.gz中找到该jar包)添加到项目的classpath中,将HBase集群的hbase-site.xml配置文件添加到项目的resources目录下。为了查看日志输出配置了一个简单的log4j.properties,也一并放到resources目录下。 
log4j.properties 内容如下:

log4j.rootLogger=WARN, A1


# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

4.2  获得连接

/**
  * project:hadoop-phoenix
  * file:BaseDB.java
  * time:2015年5月4日 下午2:19:57
  * description:
  */
package cn.com.dimensoft.hadoop.phoenix.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;

/**
 * class: BaseDB
 * package: cn.com.dimensoft.hadoop.phoenix.jdbc
 * time: 2015年5月4日 下午2:19:57
 * description: 
 */
public class BaseDB {

    /**
     * 
     * name:getConnection
     * time:2015年5月6日 下午2:07:06
     * description: get JDBC connection
     * @return connection
     */
    public static Connection getConnection() {
        try {
            // load driver
            Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");

            // get connection
            // jdbc 的 url 类似为 jdbc:phoenix [ :<zookeeper quorum> [ :<port number> ] [ :<root node> ] ],
            // 需要引用三个参数:hbase.zookeeper.quorum、hbase.zookeeper.property.clientPort、and zookeeper.znode.parent,
            // 这些参数可以缺省不填而在 hbase-site.xml 中定义。
            return DriverManager.getConnection("jdbc:phoenix");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}

4.3 创建表

/**
     * 
     * name:create
     * time:2015年5月4日 下午2:58:31
     * description:create table
     */
    public static void create() {
        Connection conn = null;
        try {
            // get connection
            conn = BaseDB.getConnection();

            // check connection
            if (conn == null) {
                System.out.println("conn is null...");
                return;
            }

            // check if the table exist
            ResultSet rs = conn.getMetaData().getTables(null, null, "USER",
                    null);
            if (rs.next()) {
                System.out.println("table user is exist...");
                return;
            }
            // create sql
            String sql = "CREATE TABLE user (id varchar PRIMARY KEY,INFO.account varchar ,INFO.passwd varchar)";

            PreparedStatement ps = conn.prepareStatement(sql);

            // execute
            ps.execute();
            System.out.println("create success...");

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

4.4 插入数据

/**
     * 
     * name:insert
     * time:2015年5月4日 下午2:59:11
     * description:
     */
    public static void upsert() {

        Connection conn = null;
        try {
            // get connection
            conn = BaseDB.getConnection();

            // check connection
            if (conn == null) {
                System.out.println("conn is null...");
                return;
            }

            // create sql
            String sql = "upsert into user(id, INFO.account, INFO.passwd) values('001', 'admin', 'admin')";

            PreparedStatement ps = conn.prepareStatement(sql);

            // execute upsert
            String msg = ps.executeUpdate() > 0 ? "insert success..."
                    : "insert fail...";

            // you must commit
            conn.commit();
            System.out.println(msg);

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

4.5 查询数据

/**
     * 
     * name:query
     * time:2015年5月4日 下午3:58:12
     * description:query data
     */
    public static void query() {

        Connection conn = null;
        try {
            // get connection
            conn = BaseDB.getConnection();

            // check connection
            if (conn == null) {
                System.out.println("conn is null...");
                return;
            }

            // create sql
            String sql = "select * from user";

            PreparedStatement ps = conn.prepareStatement(sql);

            ResultSet rs = ps.executeQuery();

            System.out.println("id" + "\t" + "account" + "\t" + "passwd");
            System.out.println("======================");

            if (rs != null) {
                while (rs.next()) {
                    System.out.print(rs.getString("id") + "\t");
                    System.out.print(rs.getString("account") + "\t");
                    System.out.println(rs.getString("passwd"));
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

4.6 更新数据

更新数据的操作与插入数据相同

4.7 删除数据

/**
     * 
     * name:delete
     * time:2015年5月4日 下午4:03:11
     * description:delete data
     */
    public static void delete() {

        Connection conn = null;
        try {
            // get connection
            conn = BaseDB.getConnection();

            // check connection
            if (conn == null) {
                System.out.println("conn is null...");
                return;
            }

            // create sql
            String sql = "delete from user where id='001'";

            PreparedStatement ps = conn.prepareStatement(sql);

            // execute upsert
            String msg = ps.executeUpdate() > 0 ? "delete success..."
                    : "delete fail...";

            // you must commit
            conn.commit();
            System.out.println(msg);

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

4.8 删除表

/**
     * 
     * name:drop
     * time:2015年5月4日 下午4:03:35
     * description:drop table
     */
    public static void drop() {

        Connection conn = null;
        try {
            // get connection
            conn = BaseDB.getConnection();

            // check connection
            if (conn == null) {
                System.out.println("conn is null...");
                return;
            }

            // create sql
            String sql = "drop table user";

            PreparedStatement ps = conn.prepareStatement(sql);

            // execute
            ps.execute();

            System.out.println("drop success...");

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

 4.9说明

在使用phoenix的JDBC驱动连接HBase,进行数据添加的时候发现数据总是无法插入,并且log日志也没有任何报错信息,最后发现是没有手动commit的缘故,phoenix并没有帮我们做commit的操作,需要我们自己手动commit。最后在执行executeUpdate后添加commit代码后数据被成功插入。

5 配置使用Squirrel GUI连接Phoenix

5.1  说明

本篇主要介绍使用Squirrel GUI客户端来连接phoenix,就像MySQL使用Navicat for MySQL,Oracle使用Pl/sql developer一样,在进行一些数据库操作的时候能够更加的直观和方便。安装过程参考官方文档,步骤稍有不同。http://phoenix.apache.org/installation.html#SQL_Client
1. Remove prior phoenix-[version]-client.jar from the lib directory of SQuirrel 
2. Start SQuirrel and add new driver to SQuirrel (Drivers -> New Driver) 
3. In the “Extra Class Path” tab, add the path to the phoenix-[version-client.jar. 
4. In Add Driver dialog box, set Name to Phoenix, and set the Example URL to jdbc:phoenix:localhost. 
5. Press List Drivers button and org.apache.phoenix.jdbc.PhoenixDriver should be automatically populated in the Class Name textbox. Press OK to close this dialog. 
6. Switch to Alias tab and create the new Alias (Aliases -> New Aliases) 
7. In the dialog box, Name: any name, Driver: Phoenix, User Name: anything, Password: anything 
8. Construct URL as follows: jdbc:phoenix: zookeeper quorum server. For example, to connect to a local HBase use: jdbc:phoenix:localhost 
9. Press Test (which should succeed if everything is setup correctly) and press OK to close. 
10. Now double click on your newly created Phoenix alias and click Connect. Now you are ready to run SQL queries against Phoenix. 

5.2 下载

从官网下载系统对应的安装包

http://squirrel-sql.sourceforge.net/

这里写图片描述

5.3 安装

直接双击下载下来的安装包进行傻瓜式安装一路Next即可(我这里下载的安装包是jar包形式)。

这里写图片描述

5.4 配置

安装好的Squirrel需要进行一些额外的配置,例如拷贝jar包和配置驱动等。

5.4.1 拷贝jar包

将phoenix-4.2.2-client.jar拷贝到squirrel安装目录的lib目录下。

高能预警:phoenix-4.2.2-client.jar可以从Phoenix的安装目录中找到,如果是其他版本的Phoenix则替换为相应的phoenix-[version]-client.jar

5.4.2 启动Squirrel

进入squirrel安装目录双击squirrel-sql.bat来启动squirrel。

这里写图片描述

5.4.3 配置Driver

进入Drivers标签页创建新的Driver。

这里写图片描述
参数说明:

Name:phoenix(可以填写其他名称) 
ExampleURL:填写HBase集群的zookeeper集群的连接信息,这里是jdbc:phoenix:192.168.187.128,192.168.187.129,192.168.187.130:2181 
Website URL:这里不填写 
Java Class Path:选择phoenix-4.2.2-client.jar(是否选中无所谓,只要在Java Class Path里面就行) 
Class Name:org.apache.phoenix.jdbc.PhoenixDriver

5.4.4 配置Aliases

进入Aliases标签页创建新的Alias。

这里写图片描述 
参数说明:

Name:phoenix(可以填写其他名称) 
Driver:选择phoenix,即上一步创建的Driver 
URL:这里就是HBase集群的zookeeper的连接ip和port 
User Name:随便填写 
Password:随便填写

这里可以点击Test进行连接测试

这里写图片描述

5.5 使用

在Aliases标签中双击刚刚创建的phoenix打开连接。

这里写图片描述

点击SQL标签进入sql命令行界面。

这里写图片描述

编写sql语句并执行

这里写图片描述

在GUI中也可以看到表的字段、视图、索引等信息,这里就不一一叙述了。

6 映射HBase数据表

6.1 说明

安装好phoenix后对于HBase中已经存在的数据表不会自动进行映射,所以想要再phoenix中操作HBase已有数据表就需要手动进行配置。

6.2 创建HBase表

> create 'phoenix','info'

6.3 插入数据

> put 'phoenix', 'row001','info:name','phoenix'
> put 'phoenix', 'row002','info:name','hbase'

这里写图片描述

高能预警:HBase数据表默认主键列名是ROW

6.4 创建Phoenix表

在Phoenix中创建相同结构的数据表

> create table "phoenix"(ROW varchar primary key, "info"."name" varchar);

预警高能:这里一定要注意的是表名和列族以及列名需要用双引号括起来,因为HBase是区分大小写的,如果不用双引号括起来的话Phoenix在创建表的时候会自动将小写转换为大写字母,这样HBase中会创建另外一张表PHOENIX。

6.5 验证

在Phoenix的CLI界面查看数据。

> select * from "phoenix";

这里写图片描述

高能预警:这里查询表名需要用双引号括起来,强制不转换为大写。

映射成功,以后就可以直接从通过phoenix来操作HBase中的“phoenix”这张表。

7 使用Phoenix自带的工具执行sql脚本

7.1 说明

phoenix自带了执行sql脚本的功能,这样方便了希望能够直接将一些关系型数据库的数据进行迁移到HBase(也可以直接使用sqoop进行导入)。

7.2 创建脚本

【PHOENIX_HOME】目录下创建user.sql,内容如下:

-- create table user
create table if not exists user (id varchar primary key,account varchar ,passwd varchar);

-- insert data
upsert into user(id, account, passwd) values('001', 'admin', 'admin');
upsert into user(id, account, passwd) values('002', 'test', 'test');
upsert into user(id, account, passwd) values('003', 'zx', 'zx');

-- query data
select * from user;

7.3 执行脚本

【PHOENIX_HOME】目录下执行脚本:

$ ./bin/psql.py 192.168.187.128,192.168.187.129,192.168.187.130:2181 user.sql

高能预警:192.168.187.128,192.168.187.129,192.168.187.130:2181这一串参数是HBase集群的zookeeper集群ip与端口号。

8 Phoenix使用MapReduce加载大批量数据

8.1 说明

在实际应用场景中可以会有一些格式比较规整的数据文件需要导入到HBase,Phoenix提供了两种方法来加载CSV格式的文件phoenix的数据表。一种是使用单线程的psql工具进行小批量数据加载的方式,一种是使用MapReduce作业来处理大批量数据的方式。第一种方式比较简单这里就不介绍了,想了解的可以参考官方文档。

http://phoenix.apache.org/bulk_dataload.html

8.2 创建表

在phoenix的CLI界面创建user表。

> create table user (id varchar primary key,account varchar ,passwd varchar);

8.3 添加测试数据

【PHOENIX_HOME】目录下创建data_import.txt,内容如下:

001,google,AM 
002,baidu,BJ 
003,alibaba,HZ

8.4 执行MapReduce

【PHOENIX_HOME】目录下执行MR作业(命令的使用跟Phoenix的版本有关)。

$ HADOOP_CLASSPATH=/usr/local/cdh-5.2.0/hbase-0.98.6/lib/hbase-protocol-0.98.6-cdh5.2.0.jar:/usr/local/cdh-5.2.0/hbase-0.98.6/conf hadoop jar phoenix-4.2.2-client.jar org.apache.phoenix.mapreduce.CsvBulkLoadTool -t user -i file:///usr/local/cdh-5.2.0/phoenix-4.2.2/data_import.txt -z 192.168.187.128,192.168.187.129,192.168.187.130:2181

参数含义如下表:

这里写图片描述

高能预警:hbase-protocol-0.98.6-cdh5.2.0.jar这个jar包是与HBase的版本有关的,如果是其他版本的HBase请自行替换。

数据文件的路径会默认读取HDFS的文件,这里强制添加前缀file:///指定为本地文件路径了,但是MR执行的过程中还是报错了说找不到文件路径:

Error: java.io.FileNotFoundException: File file:/usr/local/cdh-5.2.0/phoenix-4.2.2/data_import.txt does not exist 
at org.apache.hadoop.fs.RawLocalFileSystem.deprecatedGetFileStatus(RawLocalFileSystem.java:524) 
at org.apache.hadoop.fs.RawLocalFileSystem.getFileLinkStatusInternal(RawLocalFileSystem.java:737) 
at org.apache.hadoop.fs.RawLocalFileSystem.getFileStatus(RawLocalFileSystem.java:514) 
at org.apache.hadoop.fs.FilterFileSystem.getFileStatus(FilterFileSystem.java:398) 
at org.apache.hadoop.fs.ChecksumFileSystem$ChecksumFSInputChecker.(ChecksumFileSystem.java:140)

 但是最后数据却被成功加载到phoenix中。

这里写图片描述

最终将测试数据data_import.txt放到了HDFS的/phoenix/test/目录下,使用如下命令执行后全程无任何报错。

al/cdh-5.2.0/hbase-0.98.6/conf hadoop jar phoenix-4.2.2-client.jar org.apache.phoenix.mapreduce.CsvBulkLoadTool -t user -i /phoenix/test/data_import.txt -z 192.168.187.128,192.168.187.129,192.168.187.130:2181

该作业会被提交到YARN由ResourceManager进行资源分配

猜你喜欢

转载自blog.csdn.net/qq1226317595/article/details/80375009