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. html


Apache Phoenix是構建在HBase之上的關係型數據庫層,做爲內嵌的客戶端JDBC驅動用以對HBase中的數據進行低延遲訪問。Apache Phoenix會將用戶編寫的sql查詢編譯爲一系列的scan操做,最終產生通用的JDBC結果集返回給客戶端。數據表的元數據存儲在HBase的表中被會標記版本號,因此進行查詢的時候會自動選擇正確的schema。直接使用HBase的API,結合協處理器(coprocessor)和自定義的過濾器的話,小範圍的查詢在毫秒級響應,千萬數據的話響應速度爲秒級。java

1.1 Phoenix在Hadoop生態系統中的位置

Phoenix在Hadoop生態系統中的位置

1.2 Phoenix官網

http://phoenix.apache.org/node

2 安裝說明

本篇主要介紹Phoenix的安裝部署。sql

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 下載

從官網下載安裝包apache

http://phoenix.apache.org/download.html服務器

這裏須要注意不一樣版本的phoenix與HBase的兼容性app

這裏寫圖片描述

我目前使用的HBase版本爲hbase-0.98.6-cdh5.2.0,所以下載phoenix4.x的maven

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進行資源分配

相關文章
相關標籤/搜索