hbase構建二級索引的實現方式有哪些 hbase solr二級索引



文章插圖
hbase構建二級索引的實現方式有哪些 hbase solr二級索引

文章插圖
Phoenix 在 HBase 生態系統中占據了非常重要的地位,本文主要包括以下幾方面內容:
Phoenix 介紹CDH HBase 集成 Phoenix使用 Phoenix 創建 HBase 二級索引Phoenix 索引類型介紹Phoenix 介紹
Phoenix 是構建在 HBase 之上的高效的 SQL 引擎,同時具備 OLTP 和 OLAP 能力,作為 HBase 生態系統中非常重要的組件,重點的特性包括:
底層存儲基于 HBase,并提供一套標準的 JDBC API 作為 HBase SQL 層;支持標準 SQL,以及完整 ACID 事務特性;為 HBase 提供了二級索引解決方案;
此外,Phoenix 還和很多其他組件做了集成,比如 Spark、Hive、Flume 等 。Phoenix 與 HBase 集成,其最大的特點就是為 HBase 提供了二級索引,后文會重點介紹 。下圖是 Phoenix 的基本架構:
CDH HBase 集成 Phoenix版本說明http://phoenix.apache.org/download.html;高版本 CDH 安裝 Phoenix 可以參考:產品 | Cloudera正式宣布在CDH中支持Apache Phoenixhttp://archive.cloudera.com/cloudera-labs/phoenix/parcels/此外,用戶還可以自行編譯適合自己的Phoenix版本 。安裝
首先到官網下載適合自己環境的 Parcel 安裝包,并發布到 httpd 服務:
[[email protected] /var/www/html/phoenix/4.14.0]$ lltotal 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 遠程 Parcel 存儲庫 url:
接下來下載,分配,激活完成安裝即可 。配置
安裝完 Phoenix 后,需要做一些必要配置才能使用 Phoenix,CDH HBase 配置界面配置如下兩處:
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,如下:
[[email protected] ~]$ phoenix-phoenix-performance.py phoenix-psql.py phoenix-sqlline.py phoenix-utils.py(可左右滑動)
執行 phoenix-sqlline.py 初始化使用 Phoenix:
然后我們查看下 HBase 中 Phoenix 的系統表:
hbase(main):003:0> listSYSTEM:CATALOGSYSTEM:FUNCTIONSYSTEM:LOGSYSTEM:MUTEXSYSTEM:SEQUENCESYSTEM: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=> 2799827hbase(main):018:0> scan 'ns1000:operate_log', LIMIT => 1ROW COLUMN+CELLx00x00x12x12x00x00x00x0D1538216707720 column=f:appVersion, timestamp=1538216707892, value=http://www.mnbkw.com/jxjc/187708/2.22.0x00x00x12x12x00x00x00x0D1538216707720 column=f:area, timestamp=1538216707892, value=xE6xB1x9FxE5x8Cx97xE5x8CxBAx00x00x12x12x00x00x00x0D1538216707720 column=f:authId, timestamp=1538216707892, value=x00x00x12x12x00x00x00x0D1538216707720 column=f:city, timestamp=1538216707892, value=xE9x87x8DxE5xBAx86xE5xB8x82x00x00x12x12x00x00x00x0D1538216707720 column=f:imei, timestamp=1538216707892, value=AF36147F-8106-47F0-B58F-A3FB75DBE325x00x00x12x12x00x00x00x0D1538216707720 column=f:lat, timestamp=1538216707892, value=29.577587127685547x00x00x12x12x00x00x00x0D1538216707720 column=f:lon, timestamp=1538216707892, value=106.50493621826172x00x00x12x12x00x00x00x0D1538216707720 column=f:memberType, timestamp=1538216707892, value=0x00x00x12x12x00x00x00x0D1538216707720 column=f:mobileManufacturer, timestamp=1538216707892, value=iPhonex00x00x12x12x00x00x00x0D1538216707720 column=f:mobileModel, timestamp=1538216707892, value=iPhone 6 Plusx00x00x12x12x00x00x00x0D1538216707720 column=f:province, timestamp=1538216707892, value=xE9x87x8DxE5xBAx86xE5xB8x82x00x00x12x12x00x00x00x0D1538216707720 column=f:systemType, timestamp=1538216707892, value=1x00x00x12x12x00x00x00x0D1538216707720 column=f:systemVersion, timestamp=1538216707892, value=12.0x00x00x12x12x00x00x00x0D1538216707720 column=f:time, timestamp=1538216707892, value=15382167077201 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 | | false | | | || | SYSTEM | FUNCTION | SYSTEM TABLE | | | | | | false | | false | | | || | SYSTEM | LOG | SYSTEM TABLE | | | | | | true | 32 | false | | | || | SYSTEM | SEQUENCE | SYSTEM TABLE | | | | | | false | | false | | | || | SYSTEM | STATS | SYSTEM TABLE | | | | | | false | | false | | | || | ns1000 | operate_log | VIEW | | | | | | false | | 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 | ABLE | REMARKS | COLUMN_DEF | SQL_DATA_TYPE | SQL_DATETIME_SUB | CHAR_O |+------------+--------------+--------------+--------------+------------+------------+--------------+----------------+-----------------+-----------------+-----------+----------+-------------+----------------+-------------------+--------+| | ns1000 | operate_log | pk | 12 | VARCHAR | | | | | 0 | | | | | || | ns1000 | operate_log | appVersion | 12 | VARCHAR | | | | | 1 | | | | | || | ns1000 | operate_log | city | 12 | VARCHAR | | | | | 1 | | | | | || | ns1000 | operate_log | lat | 12 | VARCHAR | | | | | 1 | | | | | || | ns1000 | operate_log | lon | 12 | VARCHAR | | | | | 1 | | | | | || | ns1000 | operate_log | memberType | 12 | VARCHAR | | | | | 1 | | | | | || | ns1000 | operate_log | time | 12 | VARCHAR | | | | | 1 | | | | | |+------------+--------------+--------------+--------------+------------+------------+--------------+----------------+-----------------+-----------------+-----------+----------+-------------+----------------+-------------------+--------+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 查看具體執行計劃 。
參考:
1. HBase集成Phoenix,構建Phoenix view和table的區別
2. 如何使用Phoenix在CDH的HBase中創建二級索引
3. 產品 | Cloudera正式宣布在CDH中支持Apache Phoenix
◆Apache Hudi 0.5.1版本重磅發布
◆貝殼找房基于 Flink 的實時平臺建設
◆網易大數據基礎平臺建設之路
【hbase構建二級索引的實現方式有哪些 hbase solr二級索引】◆小米流式平臺架構演進與實踐