1.什么是Phoenix
Phoenix是構建在HBase上的一個SQL層,能讓我們用標椎的JDBC APIs而不是HBase客戶端APIs來創建表,插入數據和對HBase數據進程查詢;
Phoenix完全使用java編寫,作為HBase內嵌的JDBC驅動,Phoenix查詢引擎會將SQL查詢轉換為一個或多個HBase掃描(Scan),並編排執行以生成標椎的JDBC結果集;直接使用HBase API協同處理器自定義過濾器,對於簡單查詢來說,其性能量級是毫秒,對於百萬級的行數來說,其性能量級是秒;
2.Phoenix安裝
2.1 下載Phoenix
http://phoenix.apache.org/download.html
2.2 上傳並解壓文件
2.3 將Phoenix安裝目錄下的兩個jar包copy到hbase的lib目錄下(三台機器都需要)
2.4 將hbase-site.xml文件copy到Phoenix的bin目錄下,完成覆蓋
cd /opt/module/hbase/conf
cp hbase-site.xml /opt/module/phoenix/bin/
2.5 重啟hbase服務,開啟Phoenix服務
bin/sqlline.py hadoop102:2181
3.Phoenix測試
使用!table查看生成的元數據表:
使用!help查看Phoenix的用法
使用!exit退出Phoenix
3.1 創建數據表並導入數據
3.1.1 在Phoenix的bin目錄下,執行該語句:
使用Phoenix自帶的sql腳本文件
./psql.py localhost:2181 ../examples/WEB_STAT.sql
3.1.2 再導入指定的數據:
-t 后攜帶的是表名,CSV是數據文件
./psql.py -t WEB_STAT localhost:2181 ../examples/WEB_STAT.csv
3.2 查詢數據
3.2.1 進入Phoenix命令行,執行!table查看已經創建的表:
3.2.2 檢索該表記錄條數:
select count(1) from web_stat;
3.2.3 按照domain域名進行分組查詢:
select domain,count(1) as number from web_stat group by domain order by number;
3.3 插入表數據
3.3.1 創建新的數據表
create table us_population(state varchar(2),city varchar(15),population bigint,constraint pk primary key(state,city));
3.3.2 插入/更新數據
upsert into us_population(state,city,population) values('NY','New York',8143197); upsert into us_population(state,city,population) values('NY','New York',8143197); upsert into us_population(state,city,population) values('CA','Los Angeles',3844829); upsert into us_population(state,city,population) values('IL','Chicago',2842518); upsert into us_population(state,city,population) values('TX','Houston',2016582); upsert into us_population(state,city,population) values('PA','Philadelphia',1463281); upsert into us_population(state,city,population) values('AZ','Phoenix',1461575); upsert into us_population(state,city,population) values('TX','San Antonio',1256509); upsert into us_population(state,city,population) values('CA','San Diego',1255540); upsert into us_population(state,city,population) values('TX','Dallas',1213825); upsert into us_population(state,city,population) values('CA','San Jose',912332);
3.4 修改表數據
upsert into us_population(state,city,population) values('AZ','Phoenix',1500000);
3.5 刪除表數據
delete from us_population where state='NY';
3.6 創建帶列族的數據表
3.6.1 創建新數據表
create table us_population2("state" varchar(2),"city" varchar(15),"info"."population" bigint,constraint pk primary key("state","city"));
3.6.2 新增數據
upsert into us_population2("state","city","info"."population") values('BY','shanghai',8143197);
利用Phoenix查詢hbase時,返回結果中無法區分字段的列族,當不同列族下存在相同名稱的字段時,會產生異常(在hbase的不同列族中,不要出現相同的列名字段);
3.7 Phoenix的表映射
默認情況下,在hbase中創建的表在Phoenix中是看不到的;
在hbase的shell命令行中新建表
create 'HBASE_PHONEIX','grade'
插入數據
put 'HBASE_PHONEIX','001','grade:name','BigData' put 'HBASE_PHONEIX','001','grade:classname','B01'
如果在Phoenix中操作由hbase創建的數據表,則需要在Phoenix中進行表的映射;
映射的方式有兩種:視圖映射和表映射;
3.7.1 視圖映射
在Phoenix的4.10版本之后,推薦使用基於視圖的方式映射到hbase上的數據;僅提供高速檢索與查詢功能;刪除視圖也不會影響hbase上的數據;
刪除視圖上的數據會出現Error:ERROR 505 (4200):Table is read only這樣的異常;
創建視圖:
create view "HBASE_PHONEIX"("row" varchar primary key,"grade"."classname" varchar,"grade"."name" varchar);
select * from HBASE_PHONEIX;
3.7.2 表映射
使用Apache Phoenix創建時對hbase的表映射,有兩種方法:
1.當hbase中表已存在,創建用名表和結構即可;
2.當hbase中不存在,可以直接使用create table指令創建需要的表,並且在創建指令中可以根據需要對hbase表結構進行顯示的說明;
3.Phoenix的主鍵名稱不需要和hbase中相同,兩邊通過表格內置結構可以自動關聯起來,因為表格自動識別主鍵;
4.Phoenix中的column必須以hbase的columnFamily開頭;
在Phoenix中創建映射表:必須需要禁用表的映射規則,這樣做會降低檢索性能;
create table "HBASE_PHONEIX"("row" varchar primary key,"grade"."classname" varchar,"grade"."name" varchar)column_encodeed_bytes=0;
3.8 使用JDBC
3.8.1 開發准備,從集群中copy以下文件:
core-site.xml,hbase-site.xml,hdfs-site.xml文件放置在項目的resource目錄下;
3.8.2 導入依賴
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>4.14.3-HBase-1.4</version>
</dependency>
3.8.3 打開連接
private static Connection conn=null; private static Statement statement=null; /*打開連接*/
static { try { Class.forName("org.apache.phoenix.jdbc.PhoenixDriver"); //這里配置zookeeper地址,可單個,也可多個,可以是域名或者ip
String url="jdbc:phoenix:hadoop102:2181/hbase"; conn= DriverManager.getConnection(url); statement=conn.createStatement(); } catch (Exception e) { e.printStackTrace(); } }
3.8.4 創建數據表
/*創建數據表*/
public static void testCreateTable(String tableName) throws SQLException { String sql="create table "+tableName+" (mykey integer not null primary key,mycolumn varchar)"; statement.executeUpdate(sql); conn.commit(); System.out.println("創建數據表成功!"); conn.close(); statement.close(); }
public static void main(String[] args) throws SQLException {
testCreateTable("wn"); //創建數據表
}
3.8.5 單條插入數據
/*單條插入數據*/
public static void testUpsert() throws SQLException { String sql1="upsert into wn values(1,'test1')"; String sql2="upsert into wn values(2,'test2')"; String sql3="upsert into wn values(3,'test3')"; statement.executeUpdate(sql1); statement.executeUpdate(sql2); statement.executeUpdate(sql3); conn.commit(); System.out.println("數據已插入!"); conn.close(); statement.close(); }
public static void main(String[] args) throws SQLException { testUpsert(); //單條插入數據
}
3.8.6 刪除數據
/*刪除數據*/
public static void testDelete(String tableName) throws SQLException { String sql="delete from "+tableName+" where mykey=3"; statement.executeUpdate(sql); conn.commit(); System.out.println("刪除數據成功!"); conn.close(); statement.close(); }
public static void main(String[] args) throws SQLException {
testDelete("wn"); //刪除數據
}
3.8.7 檢索數據表中的記錄
/*檢索數據表中的記錄*/
public static void testReadAll() throws SQLException { String sql="select * from wn"; long time=System.currentTimeMillis(); ResultSet rs = statement.executeQuery(sql); conn.commit(); while (rs.next()){ //獲取字段值
int mykey = rs.getInt("mykey"); //獲取字段值
String mycolumn = rs.getString("mycolumn"); System.out.println("mykey:"+mykey+"\t"+"mycolumn:"+mycolumn); } rs.close(); conn.close(); statement.close(); }
public static void main(String[] args) throws SQLException {
testReadAll(); //檢索數據表中記錄
}