HBase 集成 Phoenix 構建二級索引實踐

Phoenix 在 HBase 生態系統中佔據了很是重要的地位,本文主要包括如下幾方面內容:html

 

  • Phoenix 介紹sql

  • CDH HBase 集成 Phoenixapache

  • 使用 Phoenix 建立 HBase 二級索引json

  • Phoenix 索引類型介紹安全

 
 
Phoenix 介紹
 
Phoenix 是構建在 HBase 之上的高效的 SQL 引擎,同時具有 OLTP 和 OLAP 能力,做爲 HBase 生態系統中很是重要的組件,重點的特性包括:

 

  • 底層存儲基於 HBase,並提供一套標準的 JDBC API 做爲 HBase SQL 層;網絡

  • 支持標準 SQL,以及完整 ACID 事務特性;架構

  • 爲 HBase 提供了二級索引解決方案;併發

 

此外,Phoenix 還和不少其餘組件作了集成,好比 Spark、Hive、Flume 等。Phoenix 與 HBase 集成,其最大的特色就是爲 HBase 提供了二級索引,後文會重點介紹。下圖是 Phoenix 的基本架構:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

CDH HBase 集成 Phoenix
版本說明
  • 針對 CDH 平臺,目前 Phoenix 官網主要提供了 Phoenix-4.14.0-cdh5.{11, 12, 13, 14}.2 版本的安裝包,包括源碼包、二進制 tar 安裝包以及 parcel 安裝包,能夠根據本身集羣 CDH 版本選擇合適的 Phoenix-4.14.0 CDH 安裝包,建議選擇 parcel 包,下載地址:http://phoenix.apache.org/download.html;

  • 高版本 CDH 安裝 Phoenix 能夠參考:產品 | Cloudera正式宣佈在CDH中支持Apache Phoenix

  • 低版本 CDH 能夠選擇安裝 CLABS_Phoenix,最大支持 Phoenix 4.7.0,parcel 包下載地址:http://archive.cloudera.com/cloudera-labs/phoenix/parcels/

  • 此外,用戶還能夠自行編譯適合本身的Phoenix版本。

安裝

首先到官網下載適合本身環境的 Parcel 安裝包,併發布到 httpd 服務:

[root@hadoop-01 /var/www/html/phoenix/4.14.0]$ ll
total 300524
-rw-r--r-- 1 root root 307722240 Feb  3 19:30 APACHE_PHOENIX-4.14.0-cdh5.11.2.p0.3-el7.parcel
-rw-r--r-- 1 root root       178 Feb  3 19:28 APACHE_PHOENIX-4.14.0-cdh5.11.2.p0.3-el7.parcel.sha512
-rw-r--r-- 1 root root      5081 Feb  3 19:30 manifest.json

(可左右滑動)app

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

而後配置成 CDH 遠程 Parcel 存儲庫 url:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

接下來下載,分配,激活完成安裝便可。

配置

安裝完 Phoenix 後,須要作一些必要配置才能使用 Phoenix,CDH HBase 配置界面配置以下兩處:ide

1. hbase-site.xml 的 HBase 服務高級配置代碼段(安全閥)

2. hbase-site.xml 的 HBase 客戶端高級配置代碼段(安全閥)

添加以下參數配置:

<!-- 二級索引支持 -->
<property>
  <name>hbase.regionserver.wal.codec</name>
  <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value>
</property>

<!-- 命名空間映射開啓,Phoenix4.8.0開始支持 -->
<property>
  <name>phoenix.schema.isNamespaceMappingEnabled</name>
  <value>true</value>
</property>
<property>
  <name>phoenix.schema.mapSystemTablesToNamespace</name>
  <value>true</value>
</property>

 

(可左右滑動)

而後,按照提示重啓HBase服務並從新部署客戶端配置便可。

命令行使用

CDH 安裝後環境變量都已經配置好了,能夠直接使用 phoenix-sqlline.py,以下:

[root@hadoop-01 ~]$ phoenix-
phoenix-performance.py  phoenix-psql.py         phoenix-sqlline.py      phoenix-utils.py

(可左右滑動)

執行 phoenix-sqlline.py 初始化使用 Phoenix:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

而後咱們查看下 HBase 中 Phoenix 的系統表:

hbase(main):003:0> list
SYSTEM:CATALOG                                                                                                                                                                                                                              
SYSTEM:FUNCTION                                                                                                                                                                                                                             
SYSTEM:LOG                                                                                                                                                                                                                                  
SYSTEM:MUTEX                                                                                                                                                                                                                                
SYSTEM:SEQUENCE                                                                                                                                                                                                                             
SYSTEM:STATS

(可左右滑動)

接下來看一下如何在 Phoenix 中建立 HBase 表的二級索引。

 

使用 Phoenix 建立 HBase 二級索引
映射已存在的 HBase 表

1. 查看 HBase 表

當前 HBase 中存在一張操做日誌表 ns1000:operate_log,數據量近280w,包括14個字段,以下:

hbase(main):017:0> count 'ns1000:operate_log', INTERVAL => 100000
...                                                                                                                                                                       
2799827 row(s) in 173.4200 seconds

=> 2799827
hbase(main):018:0> scan 'ns1000:operate_log', LIMIT => 1
ROW                                                          COLUMN+CELL                                                                                                                                                                    
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:appVersion, timestamp=1538216707892, value=2.22.0                                                                                                                     
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:area, timestamp=1538216707892, value=\xE6\xB1\x9F\xE5\x8C\x97\xE5\x8C\xBA                                                                                             
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:authId, timestamp=1538216707892, value=                                                                                                                               
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:city, timestamp=1538216707892, value=\xE9\x87\x8D\xE5\xBA\x86\xE5\xB8\x82                                                                                             
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:imei, timestamp=1538216707892, value=AF36147F-8106-47F0-B58F-A3FB75DBE325                                                                                             
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:lat, timestamp=1538216707892, value=29.577587127685547                                                                                                                
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:lon, timestamp=1538216707892, value=106.50493621826172                                                                                                                
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:memberType, timestamp=1538216707892, value=0                                                                                                                          
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:mobileManufacturer, timestamp=1538216707892, value=iPhone                                                                                                             
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:mobileModel, timestamp=1538216707892, value=iPhone 6 Plus                                                                                                             
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:province, timestamp=1538216707892, value=\xE9\x87\x8D\xE5\xBA\x86\xE5\xB8\x82                                                                                         
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:systemType, timestamp=1538216707892, value=1                                                                                                                          
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:systemVersion, timestamp=1538216707892, value=12.0                                                                                                                    
 \x00\x00\x12\x12\x00\x00\x00\x0D1538216707720               column=f:time, timestamp=1538216707892, value=1538216707720                                                                                                                    
1 row(s) in 0.0460 seconds

(可左右滑動)

2. Phoenix 中建立與 namespace 名稱一致的 schema
0: jdbc:phoenix:> create schema if not exists "ns1000";
No rows affected (0.012 seconds)

(可左右滑動)

3. Phoenix 中建立視圖,並查詢數據及條數

0: jdbc:phoenix:> use "ns1000";
No rows affected (0.021 seconds)
0: jdbc:phoenix:> create view "operate_log"(
. . . . . . . . > "pk" varchar primary key,
. . . . . . . . > "f"."appVersion" varchar,
. . . . . . . . > "f"."city" varchar,
. . . . . . . . > "f"."lat" varchar,
. . . . . . . . > "f"."lon" varchar,
. . . . . . . . > "f"."memberType" varchar,
. . . . . . . . > "f"."time" varchar);
No rows affected (6.555 seconds)
0: jdbc:phoenix:> !tables
+------------+--------------+--------------+---------------+----------+------------+----------------------------+-----------------+--------------+-----------------+---------------+---------------+-----------------+------------+--------+
| TABLE_CAT  | TABLE_SCHEM  |  TABLE_NAME  |  TABLE_TYPE   | REMARKS  | TYPE_NAME  | SELF_REFERENCING_COL_NAME  | REF_GENERATION  | INDEX_STATE  | IMMUTABLE_ROWS  | SALT_BUCKETS  | MULTI_TENANT  | VIEW_STATEMENT  | VIEW_TYPE  | INDEX_ |
+------------+--------------+--------------+---------------+----------+------------+----------------------------+-----------------+--------------+-----------------+---------------+---------------+-----------------+------------+--------+
|            | SYSTEM       | CATALOG      | SYSTEM TABLE  |          |            |                            |                 |              | false           | null          | false         |                 |            |        |
|            | SYSTEM       | FUNCTION     | SYSTEM TABLE  |          |            |                            |                 |              | false           | null          | false         |                 |            |        |
|            | SYSTEM       | LOG          | SYSTEM TABLE  |          |            |                            |                 |              | true            | 32            | false         |                 |            |        |
|            | SYSTEM       | SEQUENCE     | SYSTEM TABLE  |          |            |                            |                 |              | false           | null          | false         |                 |            |        |
|            | SYSTEM       | STATS        | SYSTEM TABLE  |          |            |                            |                 |              | false           | null          | false         |                 |            |        |
|            | ns1000       | operate_log  | VIEW          |          |            |                            |                 |              | false           | null          | false         |                 | MAPPED     |        |
+------------+--------------+--------------+---------------+----------+------------+----------------------------+-----------------+--------------+-----------------+---------------+---------------+-----------------+------------+--------+
0: jdbc:phoenix:> !columns "operate_log";
+------------+--------------+--------------+--------------+------------+------------+--------------+----------------+-----------------+-----------------+-----------+----------+-------------+----------------+-------------------+--------+
| TABLE_CAT  | TABLE_SCHEM  |  TABLE_NAME  | COLUMN_NAME  | DATA_TYPE  | TYPE_NAME  | COLUMN_SIZE  | BUFFER_LENGTH  | DECIMAL_DIGITS  | NUM_PREC_RADIX  | NULLABLE  | REMARKS  | COLUMN_DEF  | SQL_DATA_TYPE  | SQL_DATETIME_SUB  | CHAR_O |
+------------+--------------+--------------+--------------+------------+------------+--------------+----------------+-----------------+-----------------+-----------+----------+-------------+----------------+-------------------+--------+
|            | ns1000       | operate_log  | pk           | 12         | VARCHAR    | null         | null           | null            | null            | 0         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | appVersion   | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | city         | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | lat          | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | lon          | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | memberType   | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
|            | ns1000       | operate_log  | time         | 12         | VARCHAR    | null         | null           | null            | null            | 1         |          |             | null           | null              | null   |
+------------+--------------+--------------+--------------+------------+------------+--------------+----------------+-----------------+-----------------+-----------+----------+-------------+----------------+-------------------+--------+
0: jdbc:phoenix:> select * from "operate_log" limit 1;
+------------------------+-------------+-------+---------------------+---------------------+-------------+----------------+
|           pk           | appVersion  | city  |         lat         |         lon         | memberType  |      time      |
+------------------------+-------------+-------+---------------------+---------------------+-------------+----------------+
1538216707720  | 2.22.0      | 重慶市   | 29.577587127685547  | 106.50493621826172  | 0           | 1538216707720  |
+------------------------+-------------+-------+---------------------+---------------------+-------------+----------------+
1 row selected (0.115 seconds)
0: jdbc:phoenix:> select count(*) from "operate_log";
+-----------+
| COUNT(1)  |
+-----------+
| 2799827   |
+-----------+
1 row selected (3.848 seconds)

(可左右滑動)

4. 根據字段 time 進行時間範圍查詢:

0: jdbc:phoenix:> select count(*) from "operate_log" where "f"."time" between '1538216707720' and '1538223834000';
+-----------+
| COUNT(1)  |
+-----------+
| 5883      |
+-----------+
1 row selected (5.241 seconds)

(可左右滑動)

這種狀況下,基本上查詢都在 5s 左右。

 

這裏還要有兩點說明:

  • Phoenix 會自動將表名、字段名都轉成大寫,若是要區分大小寫使用雙引號括起來便可。

  • 這裏咱們建立的是視圖,至關於外部表,也能夠 create table 建立表,視圖的特色是刪除時不會刪除 HBase 表,可是視圖建立的二級索引不會自動更新,若是要實時更新的話,只能使用 create table,而後經過 Phoenix jdbc 的方式寫入數據,只有經過 Phoenix 寫,而後用 Phoenix 實現的協處理器才能實現實時更新的索引。

     

使用 Phoenix 建立二級索引

1. 使用 Phoenix 對 time 字段建立索引

0: jdbc:phoenix:> create index index_operate_log_time on "operate_log" ("f"."time");
2,799,827 rows affected (95.814 seconds)

 

(可左右滑動)

2. 再次根據 time 字段作範圍查詢

00: jdbc:phoenix:> select count(*) from "operate_log" where "f"."time" between '1538216707720' and '1538223834000';
+-----------+
| COUNT(1)  |
+-----------+
| 5883      |
+-----------+
1 row selected (0.049 seconds)

(可左右滑動)

這裏基本上查詢都在 50 ms 左右。這就是經過 Phoenix 的二級索引帶來的性能提高。

 

Phoenix 索引類型介紹

 

Phoenix 提供了多種索引類型,包括覆蓋索引、函數索引,以及全局索引與本地索引等,具體介紹以下。

Covered Indexes(覆蓋索引)

覆蓋索引是在索引表中直接存儲某些經常使用字段,當查詢時全部字段僅涉及索引表中包含的字段時,則無需再在基於 rowkey 索引的數據表中查詢,提升了查詢的效率。

 

好比,咱們在operate_log 表 "f"."time" 列上建立一個索引,並在索引中包含 "f"."lat", "f"."lon" 列:

0: jdbc:phoenix:> create index index_operate_log_time2 on "operate_log" ("f"."time") INCLUDE("f"."lat", "f"."lon");
2,799,827 rows affected (133.367 seconds)

(可左右滑動)

這樣咱們作相似以下查詢時就能夠直接走索引表,以提升查詢性能:

0: jdbc:phoenix:> select "f"."lat", "f"."lon" from "operate_log" where "f"."time" between '1538216707720' and '1538223834000' limit 10;

(可左右滑動)

Functional Indexes(函數索引)

函數索引是在 Phoeinx 4.3 版本以後新增的,它使得索引的創建不只僅只限於基於列,而可使用任意的表達式來建立索引,在查詢時,如出現相同的表達式查詢條件,則會自動優先檢索索引表。

 

好比,咱們在operate_log 表上基於 substr ( "f"."time", 1, 10) 建立一個索引:

0: jdbc:phoenix:> create index index_operate_log_time3 on "operate_log" (substr("f"."time", 1, 10));
2,799,827 rows affected (94.74 seconds)

 

(可左右滑動)

這樣建立索引後,咱們就可使用相同表達式走索引表進行查詢優化了,好比:

0: jdbc:phoenix:> select count(*) from "operate_log" where substr("f"."time", 1, 10) between '1538216707' and '1538223834';
+-----------+
| COUNT(1)  |
+-----------+
| 5886      |
+-----------+
1 row selected (0.059 seconds)

 

(可左右滑動)

Global Indexes(全局索引)

上面的覆蓋索引和函數索引都屬於全局索引,也是 Phoenix 默認的索引建立模式。

 

全局索引將索引表和數據表分開存儲,如以上例子中都會建立一張新的索引表,所以每條數據和其索引數據可能會分佈在不一樣的數據節點上,數據表的添加、刪除和修改都會更新相關的索引表,因此寫入數據時因爲額外的網絡開銷會帶來較大的性能消耗。而查詢數據的時候,Phoenix 會經過索引表來快速低損耗的獲取數據。所以全局索引更適合讀多寫少的使用場景。

Local Indexes(本地索引)

本地索引與全局索引相反,在 4.8.0 版本以後會將索引數據以特定的列簇存儲在同一張數據表中,並經過特定的 rowkey 設置,將每條數據及其索引數據存儲在同一 region 中,所以在數據寫入時防止了額外的網絡開銷,而在讀取數據時因沒法提早判斷索引數據的準確位置,則會在全部的 region 中檢索索引數據,而很是影響讀取性能。因此本地索引更適合於寫多讀少的使用場景。

 

本地索引只要在原來索引建立時增長 local 關鍵字便可,好比:

0: jdbc:phoenix:> create local index index_operate_log_time on "operate_log" ("f"."time");

 

(可左右滑動)

 

總結

 

Phoenix 是構建在 HBase 之上的 SQL 層,不只可以提供標準的 SQL 查詢,還可以爲 HBase 提供二級索引能力,在 HBase 使用場景中應用很是普遍。Phoenix 二級索引主要分爲全局索引和本地索引,全局索引適合那些讀多寫少的場景,本地索引更適合那些寫多讀少的場景。判斷是否走索引能夠 explain SQL 查看具體執行計劃。

            watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

相關文章
相關標籤/搜索