HBase 集成 Phoenix 构建二级索引实践
Phoenix 在 HBase 生態(tài)系統(tǒng)中占據(jù)了非常重要的地位,本文主要包括以下幾方面內(nèi)容:
-
Phoenix 介紹
-
CDH HBase 集成?Phoenix
-
使用 Phoenix 創(chuàng)建 HBase 二級索引
-
Phoenix 索引類型介紹
Phoenix 介紹
Phoenix 是構(gòu)建在 HBase 之上的高效的 SQL 引擎,同時具備 OLTP 和 OLAP 能力,作為 HBase 生態(tài)系統(tǒng)中非常重要的組件,重點(diǎn)的特性包括:
-
底層存儲基于 HBase,并提供一套標(biāo)準(zhǔn)的 JDBC API 作為 HBase SQL 層;
-
支持標(biāo)準(zhǔn) SQL,以及完整 ACID 事務(wù)特性;
-
為 HBase 提供了二級索引解決方案;
此外,Phoenix 還和很多其他組件做了集成,比如 Spark、Hive、Flume 等。Phoenix 與 HBase 集成,其最大的特點(diǎn)就是為 HBase 提供了二級索引,后文會重點(diǎn)介紹。下圖是 Phoenix 的基本架構(gòu):
CDH HBase 集成 Phoenix
版本說明
-
針對 CDH 平臺,目前 Phoenix 官網(wǎng)主要提供了 Phoenix-4.14.0-cdh5.{11, 12, 13, 14}.2 版本的安裝包,包括源碼包、二進(jìn)制 tar 安裝包以及 parcel 安裝包,可以根據(jù)自己集群 CDH 版本選擇合適的 Phoenix-4.14.0 CDH 安裝包,建議選擇 parcel 包,下載地址:http://phoenix.apache.org/download.html;
-
高版本 CDH 安裝 Phoenix 可以參考:產(chǎn)品 | Cloudera正式宣布在CDH中支持Apache Phoenix
-
低版本 CDH 可以選擇安裝 CLABS_Phoenix,最大支持 Phoenix 4.7.0,parcel 包下載地址:http://archive.cloudera.com/cloudera-labs/phoenix/parcels/
-
此外,用戶還可以自行編譯適合自己的Phoenix版本。
安裝
首先到官網(wǎng)下載適合自己環(huán)境的 Parcel 安裝包,并發(fā)布到 httpd 服務(wù):
[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然后配置成 CDH 遠(yuǎn)程 Parcel 存儲庫 url:
接下來下載,分配,激活完成安裝即可。
配置
安裝完 Phoenix 后,需要做一些必要配置才能使用 Phoenix,CDH HBase 配置界面配置如下兩處:
1. hbase-site.xml 的 HBase 服務(wù)高級配置代碼段(安全閥)
2. hbase-site.xml 的 HBase 客戶端高級配置代碼段(安全閥)
添加如下參數(shù)配置:
<!--?二級索引支持?--> <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服務(wù)并重新部署客戶端配置即可。
命令行使用
CDH 安裝后環(huán)境變量都已經(jīng)配置好了,可以直接使用 phoenix-sqlline.py,如下:
[root@hadoop-01?~]$?phoenix- phoenix-performance.py??phoenix-psql.py?????????phoenix-sqlline.py??????phoenix-utils.py執(zhí)行 phoenix-sqlline.py 初始化使用 Phoenix:
然后我們查看下 HBase 中 Phoenix 的系統(tǒng)表:
hbase(main):003:0>?list SYSTEM:CATALOG?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? SYSTEM:FUNCTION????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? SYSTEM:LOG?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? SYSTEM:MUTEX???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? SYSTEM:SEQUENCE????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? SYSTEM:STATS?接下來看一下如何在 Phoenix 中創(chuàng)建 HBase 表的二級索引。
使用 Phoenix 創(chuàng)建 HBase 二級索引
映射已存在的 HBase 表
1. 查看 HBase 表
當(dāng)前 HBase 中存在一張操作日志表 ns1000:operate_log,數(shù)據(jù)量近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?seconds2. Phoenix 中創(chuàng)建與 namespace 名稱一致的 schema
0:?jdbc:phoenix:>?create?schema?if?not?exists?"ns1000"; No?rows?affected?(0.012?seconds)3. Phoenix 中創(chuàng)建視圖,并查詢數(shù)據(jù)及條數(shù)
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. 根據(jù)字段 time 進(jìn)行時間范圍查詢:
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 左右。
這里還要有兩點(diǎn)說明:
-
Phoenix 會自動將表名、字段名都轉(zhuǎn)成大寫,如果要區(qū)分大小寫使用雙引號括起來即可。
-
這里我們創(chuàng)建的是視圖,相當(dāng)于外部表,也可以 create table 創(chuàng)建表,視圖的特點(diǎn)是刪除時不會刪除 HBase 表,但是視圖創(chuàng)建的二級索引不會自動更新,如果要實(shí)時更新的話,只能使用?create table,然后通過?Phoenix jdbc 的方式寫入數(shù)據(jù),只有通過?Phoenix 寫,然后用?Phoenix 實(shí)現(xiàn)的協(xié)處理器才能實(shí)現(xiàn)實(shí)時更新的索引。
使用 Phoenix 創(chuàng)建二級索引
1. 使用 Phoenix 對 time 字段創(chuàng)建索引
0:?jdbc:phoenix:>?create?index?index_operate_log_time?on?"operate_log"?("f"."time"); 2,799,827?rows?affected?(95.814?seconds)2. 再次根據(jù) 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 提供了多種索引類型,包括覆蓋索引、函數(shù)索引,以及全局索引與本地索引等,具體介紹如下。
Covered Indexes(覆蓋索引)
覆蓋索引是在索引表中直接存儲某些常用字段,當(dāng)查詢時所有字段僅涉及索引表中包含的字段時,則無需再在基于 rowkey 索引的數(shù)據(jù)表中查詢,提高了查詢的效率。
比如,我們在operate_log 表 "f"."time" 列上創(chuàng)建一個索引,并在索引中包含 "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(函數(shù)索引)
函數(shù)索引是在?Phoeinx 4.3 版本之后新增的,它使得索引的建立不僅僅只限于基于列,而可以使用任意的表達(dá)式來創(chuàng)建索引,在查詢時,如出現(xiàn)相同的表達(dá)式查詢條件,則會自動優(yōu)先檢索索引表。
比如,我們在operate_log 表上基于?substr (?"f"."time", 1, 10)?創(chuàng)建一個索引:
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)這樣創(chuàng)建索引后,我們就可以使用相同表達(dá)式走索引表進(jìn)行查詢優(yōu)化了,比如:
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(全局索引)
上面的覆蓋索引和函數(shù)索引都屬于全局索引,也是 Phoenix 默認(rèn)的索引創(chuàng)建模式。
全局索引將索引表和數(shù)據(jù)表分開存儲,如以上例子中都會創(chuàng)建一張新的索引表,因此每條數(shù)據(jù)和其索引數(shù)據(jù)可能會分布在不同的數(shù)據(jù)節(jié)點(diǎn)上,數(shù)據(jù)表的添加、刪除和修改都會更新相關(guān)的索引表,所以寫入數(shù)據(jù)時由于額外的網(wǎng)絡(luò)開銷會帶來較大的性能消耗。而查詢數(shù)據(jù)的時候,Phoenix 會通過索引表來快速低損耗的獲取數(shù)據(jù)。因此全局索引更適合讀多寫少的使用場景。
Local?Indexes(本地索引)
本地索引與全局索引相反,在 4.8.0 版本之后會將索引數(shù)據(jù)以特定的列簇存儲在同一張數(shù)據(jù)表中,并通過特定的 rowkey 設(shè)置,將每條數(shù)據(jù)及其索引數(shù)據(jù)存儲在同一 region 中,因此在數(shù)據(jù)寫入時防止了額外的網(wǎng)絡(luò)開銷,而在讀取數(shù)據(jù)時因無法提前判斷索引數(shù)據(jù)的準(zhǔn)確位置,則會在所有的 region 中檢索索引數(shù)據(jù),而非常影響讀取性能。所以本地索引更適合于寫多讀少的使用場景。
本地索引只要在原來索引創(chuàng)建時增加 local 關(guān)鍵字即可,比如:
0:?jdbc:phoenix:>?create?local?index?index_operate_log_time?on?"operate_log"?("f"."time");總結(jié)
Phoenix 是構(gòu)建在 HBase 之上的 SQL 層,不僅能夠提供標(biāo)準(zhǔn)的 SQL 查詢,還能夠?yàn)?HBase 提供二級索引能力,在 HBase 使用場景中應(yīng)用非常廣泛。Phoenix 二級索引主要分為全局索引和本地索引,全局索引適合那些讀多寫少的場景,本地索引更適合那些寫多讀少的場景。判斷是否走索引可以 explain SQL 查看具體執(zhí)行計(jì)劃。
參考:
1. HBase集成Phoenix,構(gòu)建Phoenix view和table的區(qū)別
2. 如何使用Phoenix在CDH的HBase中創(chuàng)建二級索引
3. 產(chǎn)品 | Cloudera正式宣布在CDH中支持Apache Phoenix
往期推薦
1、HBase最佳實(shí)踐 | 聊聊HBase核心配置參數(shù)
2、Apache Hudi:劍指數(shù)據(jù)湖的增量處理框架
3、Hadoop社區(qū)比 Ozone 更重要的事情
4、MapReduce Shuffle 和 Spark Shuffle 結(jié)業(yè)篇
?
總結(jié)
以上是生活随笔為你收集整理的HBase 集成 Phoenix 构建二级索引实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 复旦大学计算机专业硕士平均工资,在复旦大
- 下一篇: Antd DatePicker之旬查询(