博客已轉移,請借一步說話,http://www.daniubiji.cn/archives/111html
HBase,一個NoSQL數據庫,可存儲大量非關係型數據。java
HBase,能夠用HBase shell進行操做,也能夠用HBase Java api進行操做。HBase雖然是一個數據庫,可是它的查詢語句,很不太好用。要是能像使用Mysql等關係型數據庫同樣用sql語句操做HBase,那就很Perfect了。node
現有工具備不少Hive,Tez,Impala,Shark/Spark,Phoenix等。今天主要記錄Phoenix。mysql
phoenix,由saleforce.com開源的一個項目,後又捐給了Apache。它至關於一個Java中間件,幫助開發者,像使用jdbc訪問關係型數據庫一些,訪問NoSql數據庫HBase。linux
phoenix,操做的表及數據,存儲在hbase上。phoenix只是須要和Hbase進行表關聯起來。而後再用工具進行一些讀或寫操做。sql
其實,能夠把Phoenix只當作一種代替HBase的語法的一個工具。雖然能夠用java能夠用jdbc來鏈接phoenix,而後操做HBase,可是在生產環境中,不能夠用在OLTP中。在線事務處理的環境中,須要低延遲,而Phoenix在查詢HBase時,雖然作了一些優化,但延遲仍是不小。因此依然是用在OLAT中,再將結果返回存儲下來。shell
Phoenix官網上,對Phoenix講解已經很屌了。若是英語好,能夠看官網,更正式一些。數據庫
phoenix與HBase版本對應關係apache
Phoenix 2.x - HBase 0.94.xapi
Phoenix 3.x - HBase 0.94.x
Phoenix 4.x - HBase 0.98.1+
我目前測試使用版本概況:
Hadoop1.0.4
HBase0.94.18
因此我能夠用phoenix2.x,phoenix3.x。
官網download頁面有
我選用的是phoenix3.1.0版本。
tar –zxvf phoenix.tar.gz
pwd
/root/phoenix
ll phoenix
phoenix目錄結構可能會有點不一樣,主要是bin目錄的位置,可能在hadoop1下,也可能直接在 /root/phoenix下。不要緊,都差很少。
既然用的hadoop1.x集羣,那麼咱們使用phoenix目錄下,hadoop1目錄下的內容。
①將hadoop1下,phoenix-core-3.x.jar拷貝到hadoop集羣各個節點HBase的lib目錄下。
②重啓一下HBase
在主節點上,切換到/root/phoenix/hadoop1/bin目錄下
輸入 ./sqlline.py master:2181
若是出現這個畫面,那就是成功了。若是不成功,多是zookeeper配置的有一些問題吧。
好吧,先退出此界面,輸入!quit回車而後就能夠退出了。
這個phoenix挺有意思,有一些命令須要輸入歎號的!
mysql的話,能夠CLI命令行的方式操做;能夠經過用jdbc,在Java代碼中訪問;能夠經過用SQLyog進行訪問管理;
phoenix,怎麼用呢?~能夠當作是mysql。Phoenix能夠在CLI下操做;能夠用jdbc操做;能夠用phoenix的一個客戶端工具Squirrel 訪問;
先說Squirrel吧,這個簡單一些。
Squirrel SQL Client,是一個鏈接數據庫的客戶端工具。通常支持JDBC的數據庫均可以用它來鏈接。(如Squirrel鏈接Mysql)
下載Squirrel SQL Client,解壓縮就能夠了。運行squirrel-sql.bat就出現了圖形界面。
①在Squirrel安裝目錄的lib下,添加幾個jar包
a,phoenix-core-xxx.jar
b,phoenix-3.0-client.jar
c,hbase-0.94.18.jar
d,hadoop1.0.4.jar
e,hadoop-common-xxx.jar
②
須要點擊「Drivers」,將phoenix的驅動添加進去。
③點擊左上角 藍色的 「 + 」 加號,添加
按上面的順序,依次填寫。第一步Name:隨便寫個名字,標記鏈接;第二步Example URL:至關於mysql的jdbc鏈接串,這裏的alias寫zookeeper的主機名稱,端口號,能夠寫,能夠不寫,我通常不寫;第三步選擇Phoenix-core的jar包;第四步就是手動輸入org.apache.phoenix.jdbc.PhoenixDriver。
而後點擊OK。
④配置鏈接
Name:爲隨便起的名稱。
Driver:選中③中添加的phoenix驅動。
URL:寫如上內容,jdbc:phoenix:node1,node2,master等這裏主要是zookeeper主機名。
User Name:要鏈接的主機的用戶名
Password:要鏈接的主機的密碼
點擊Test能夠進行測試,或點OK鏈接。
鏈接完畢,啓動後,就能夠看到以下的效果了。這裏我已經建立了幾個表了,這些表都是存在於HBase上的。
1,用squirrel創建的一些鏈接
2,當前鏈接下,全部對象,包括主見系統表,普通表,視圖。
3,爲表,這些表都是實際存在於zookeeper所管理的HBase上的。右鍵此表,能夠對錶進行管理。
4,爲視圖。
5,編寫sql腳本的地方,能夠輸入腳本執行。腳本執行方式,在5上面有一個小人,選中sql,點擊小人就能夠執行了。或者按ctrl + enter鍵,執行。
6,爲選中的對象的一些基本信息,列信息,行數等。
7,爲sql執行的一些狀態。
下面在Squirrel中建立一個表
在Squirrel中建立表的過程主要是編寫sql,進行執行。sql該怎麼寫,須要看phoenix驅動都支持什麼效果。
這須要看phoenix的官網了。
須要注意的是phoenix是區分大小寫的,本身定義的HBase中的 HTableName,ColumnFamily,以及字段Column,須要和Phoenix中保持一致。
phoenix操做hbase,咱們有兩種方式,建立表,建立視圖。
這兩種方式,有區別。
好比,建立表的話,就能夠對HBase進行插入,查詢,刪除操做。視圖的話,通常就只能夠進行查詢操做
雖然看起來,表的功能,比視圖更強大一些。可是就像是mysql等關係型數據庫同樣,刪除表操做,會將表刪掉。可是刪除視圖操做,卻不會影響原始表的結構。
由於使用phoenix,建立表後,會自動和hbase創建關聯映射。當你使用phoenix刪除和hbase之間的關係時,就會將hbase中的表也刪掉了
因此用視圖,會對原始的HBase表影響小一些。
phoenix能夠建立表,
若hbase中,不存在HTable:
create htablename (
pk VARCHAR primary key not null,
col1 VARCHAR null,
col2 VARCHAR null,
col3 VARCHAR null
)
create htablename2(
pk VARCHAR primary key null,
"cf"."col1" VARCHAR null,
"cf"."col2" VARCHAR null,
"cf2"."col3" VARCHAR null,
"cf2"."col4" VARCHAR null,
)
上面的SQL腳本,能夠在SQuirreL中進行執行,執行過程當中,若是出現錯誤,會在工具的下面進行提示。若成功後,就能夠在HBase中看到這個表了。
若Hbase中,已存在名爲htablename3的HTable,那麼SQuirrel是不會直接顯示出hbase中這個已存在的表的,咱們還須要額外作一些操做。
在SQuirreL中進行執行,執行完畢後,就會將HBase的htablename3,映射到SQuirreL中。這樣咱們就能夠在Java api中進行操做了。不然是不能夠的。
那麼須要哪些具體操做呢?其實很簡單,我當時沒想到
就像建立表同樣,使用Create table就能夠了。就這樣簡單。
不過這個語句怎麼寫呢?怎樣對應呢?
create htablename3(
pk VARCHAR primary key null, -------這句話直接寫就能夠了,這樣的話,HBase中的RowKey轉換成phoenix中的主鍵,列名就叫 pk。rowkey自動會和primary key進行對應。
"cf"."col1" VARCHAR null, -------將名爲cf的columnFamily下,字段名爲col1的字段,寫在這裏。
"cf"."col2" VARCHAR null, -------將名爲cf的columnFamily下,字段名爲col2的字段,寫在這裏。。。下面就以此類推
"cf2"."col3" VARCHAR null,
"cf2"."col4" VARCHAR null,
)
而後在SQuirreL中執行,而後就能夠看到數據了。
不過此時,可能還會有問題,亂碼。 在SQuirrel中,主鍵以及一些包含漢字的字段,都是方塊等亂碼了。這個怎麼解決???
建立試圖
CREATE VIEW "heihei"
(pk VARCHAR primary key)
default_column_family = 'FM'
建立完成後,這裏的「heihei」 是HBase中table的名稱。而後定義一個主鍵,就能夠了。
建立視圖
①CREATE VIEW "DAMAI" ( PK VARCHAR PRIMARY KEY) DEFAULT_COLUMN_FAMILY='FM'
這裏雙引號內的 「DAMAI」 和HBase中的表名是同樣的,因此會自動關聯。
那麼,若是想針對HBase中的一個表,建多個視圖呢?
②第二種視圖,能夠在Phoenix table的基礎上建立。
CREATE VIEW my_VIEW (new_col VARCHAR,new_col2 VARCHAR) AS SELECT * FROM phoenix_Table WHERE ......
③第三種視圖,是創建在視圖之上,
CREATE VIEW my_VIEW_ON_VIEW AS SELECT * FROM MY_VIEW WHERE ......
因此說,在建立DAMAI視圖的時候,能夠將所有字段都包括進來。而後再在此視圖基礎上,建立其它視圖。
隨着數據的增加,視圖中能夠看到的數據的條數,也在同步增長。
使用命令查看一下視圖中的數據
select * from damai 這時能夠用大小寫都行了。沒有區分
查詢結果如今,只有一列。看來是建立視圖時,沒有關聯好其餘列。不要緊,刪掉,重建。
Phoenix中的語法
Phoenix中的數據類型
Phoenix中的方法
我本身使用過程當中一些簡單語句,以下:
select * from shuju;
select count(1) from shuju;
select cmtid,count(1) as num from shuju group by cmtid order by num desc;
select avg(TO_NUMBER(avgt)) from shuju;
select cmtid,count(1) as num,avg(TO_NUMBER(avgt)) as avgt,avg(TO_NUMBER(loss)) as loss from shuju group by cmtid order by num desc;
select acm,dtype,cmtid,count(1) as num,avg(TO_NUMBER(avgt)) as avgt,avg(TO_NUMBER(loss)) as loss
from shuju
group by acm,dtype,cmtid
order by num desc;
select acm,dtype,porgcode,orgid,cmtid,count(1) as num,avg(TO_NUMBER(avgt)) as avgt,avg(TO_NUMBER(loss)) as loss
from shuju
group by acm,dtype,porgcode,orgid,cmtid
order by num desc;
where TO_DATE(ttime,'yyyyMMddHHmmss')=TO_DATE('20141125','yyyyMMdd')
select ttime from shuju order by ttime desc;
where TO_DATE(ttime,'yyyyMMddHHmmss')=TO_DATE('20141125','yyyyMMdd')
select TO_DATE(ttime,'yyyyMMddHHmmss') from shuju;
select TO_DATE('20141125','yyyyMMdd') from shuju;
select (TO_DATE(ttime,'yyyyMMddHHmmss')=TO_DATE('20141125','yyyyMMdd')) as aaa from shuju order by aaa asc;
用SHELL來操做phoenix,不太好用。無助的時候,你能夠喊救命!So,Say Help Help Help
./sqlline.py master:2181
進入shell後,輸入help
能夠看到不少命令,前面都帶了一個歎號。根據意思本身猜一猜功能,而後試一試效果,就能夠了。不記錄了。
這個過程就想是JDBC同樣使用就能夠了。
①先將phoenix的 core.jar包 和 phoenix的client.jar 包放到lib裏。
②建立鏈接,過程和mysql相似
public Connection GetConnection(){
Connection cc = null;
String driver = "org.apache.phoenix.jdbc.PhoenixDriver";
//String url = "jdbc:phoenix:192.168.206.21:2181";
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (cc == null) {
try {
cc = DriverManager.getConnection(url);
} catch (SQLException e) {
e.printStackTrace();
}
}
return cc;
}
OK 搞定了。