日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

HBase phoenix二级索引

發布時間:2024/1/17 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HBase phoenix二级索引 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 為什么需要用二級索引?

對于HBase而言,如果想精確地定位到某行記錄,唯一的辦法是通過rowkey來查詢。如果不通過rowkey來查找數據,就必須逐行地比較每一列的值,即全表掃瞄。對于較大的表,全表掃描的代價是不可接受的。但是,很多情況下,需要從多個角度查詢數據。例如,在定位某個人的時候,可以通過姓名、身份證號、學籍號等不同的角度來查詢,要想把這么多角度的數據都放到rowkey中幾乎不可能(業務的靈活性不允許,對rowkey長度的要求也不允許)。所以,需要secondary index(二級索引)來完成這件事。secondary index的原理很簡單,但是如果自己維護的話則會麻煩一些。現在,Phoenix已經提供了對HBase secondary index的支持。

2. Phoenix Global Indexing And Local Indexing

2.1 Global Indexing

Global indexing,全局索引,適用于讀多寫少的業務場景。使用Global indexing在寫數據的時候開銷很大,因為所有對數據表的更新操作(DELETE, UPSERT VALUES and UPSERT SELECT),都會引起索引表的更新,而索引表是分布在不同的數據節點上的,跨節點的數據傳輸帶來了較大的性能消耗。在讀數據的時候Phoenix會選擇索引表來降低查詢消耗的時間。在默認情況下如果想查詢的字段不是索引字段的話索引表不會被使用,也就是說不會帶來查詢速度的提升。

2.2 Local Indexing

Local indexing,本地索引,適用于寫操作頻繁以及空間受限制的場景。與Global indexing一樣,Phoenix會自動判定在進行查詢的時候是否使用索引。使用Local indexing時,索引數據和數據表的數據存放在相同的服務器中,這樣避免了在寫操作的時候往不同服務器的索引表中寫索引帶來的額外開銷。使用Local indexing的時候即使查詢的字段不是索引字段索引表也會被使用,這會帶來查詢速度的提升,這點跟Global indexing不同。對于Local Indexing,一個數據表的所有索引數據都存儲在一個單一的獨立的可共享的表中。

3. Immutable index And Mutable index

3.1 immutable index

immutable index,不可變索引,適用于數據只增加不更新并且按照時間先后順序存儲(time-series data)的場景,如保存日志數據或者事件數據等。不可變索引的存儲方式是write one,append only。當在Phoenix使用create table語句時指定IMMUTABLE_ROWS = true表示該表上創建的索引將被設置為不可變索引。Phoenix默認情況下如果在create table時不指定IMMUTABLE_ROW = true時,表示該表為mutable。不可變索引分為Global immutable index和Local immutable index兩種。

3.2 mutable index

mutable index,可變索引,適用于數據有增刪改的場景。Phoenix默認情況創建的索引都是可變索引,除非在create table的時候顯式地指定IMMUTABLE_ROWS = true。可變索引同樣分為Global immutable index和Local immutable index兩種。

4.配置HBase支持Phoenix二級索引

如果要啟用phoenix的二級索引功能,需要對HMaster以及每一個RegionServer上的hbase-site.xml進行額外的配置。首先,在每一個RegionServer的hbase-site.xml里加入如下屬性:

<property> <name>hbase.regionserver.wal.codec</name> <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value> </property><property> <name>hbase.region.server.rpc.scheduler.factory.class</name><value>org.apache.hadoop.hbase.ipc.PhoenixRpcSchedulerFactory</value> <description>Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates</description> </property><property><name>hbase.rpc.controllerfactory.class</name><value>org.apache.hadoop.hbase.ipc.controller.ServerRpcControllerFactory</value><description>Factory to create the Phoenix RPC Scheduler that uses separate queues for index and metadata updates</description> </property><property><name>hbase.coprocessor.regionserver.classes</name><value>org.apache.hadoop.hbase.regionserver.LocalIndexMerger</value> </property>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

如果沒有在每個regionserver上的hbase-site.xml里面配置如上屬性,那么使用create index語句創建二級索引將會拋出如下異常:

Error: ERROR 1029 (42Y88): Mutable secondary indexes must have the hbase.regionserver.wal.codec property set to org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec in the hbase-sites.xml of every region server tableName=TEST_INDEXES (state=42Y88,code=1029)
  • 1
  • 1

然后在每一個master的hbase-site.xml里加入如下屬性:

<property><name>hbase.master.loadbalancer.class</name> <value>org.apache.phoenix.hbase.index.balancer.IndexLoadBalancer</value> </property><property><name>hbase.coprocessor.master.classes</name><value>org.apache.phoenix.hbase.index.master.IndexMasterObserver</value> </property>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

完成上述修改后重啟hbase集群使配置生效。

【特別注意】?
如果使用的是CDH部署的HBase,需要在Cloudera Manager管理頁面里面的HBase“配置”頁面里的hbase-site.xml項增加上述配置,并在管理頁面里面重啟HBase才能使得配置生效。

5. 測試案例

5.1 測試案例1

HBase 1000w數據?
users_test表

【Global Indexing】

在沒有創建二級索引之前查詢特定USER_NAME的用戶信息耗時大約16s左右。

在USER_NAME列上面創建二級索引:

create index USERS_TEST_IDX0 on "users_test ("info".USER_NAME)
  • 1
  • 1

創建二級索引后查詢特定USER_NAME的用戶名稱耗時為ms級別

【說明】?可以通過explain命令來查看查詢是否用到二級索引

【注意】?如果在select條件里面選擇了其他的列,如USER_NO,因為該列沒有存在于索引表,因此查詢不會走索引表。

如果想在select USER_NAME,USER_NO查詢仍然走索引,必須創建如下索引:

  • 方式一,采取INCLUDE(index cover,即索引覆蓋)的方式:
create index USERS_TEST_IDX1 on "users_test"("info".USER_NAME) INCLUDE("info".USER_NO)
  • 1
  • 1

索引覆蓋其實就是將INCLUDE里面包含的列都存儲到索引表里面,當檢索的時候就可以從索引表里直接帶回這些列值。要特別注意索引列和索引覆蓋列的區別,索引列在索引表里面是以rowkey的形式存在,多個索引列以某個約定的字節分割然后一起存儲在rowkey里面,也就是說當索引列有很多個的時候,rowkey的長度也相應會變長,大小取決于索引列值的大小。而索引覆蓋列,是存儲在索引表的列族中。

  • 方式二,采取多列索引:
create index USERS_TEST_IDX2 on "users_test"("info".USER_NAME, "info".USER_NO)
  • 1
  • 1

【說明】

多列索引在滿足前綴式的情況才會用到,如創建了A,B,C順序的多列索引,當在where條件指定A條件、A B條件或者A B C條件均會走索引,但是 B C條件則無法走索引。

【Local Indexing】

在users_test表創建local index類型的二級索引:

create local index USERS_TEST_LOCAL_IDX ON "users_test"("info".USER_NAME)
  • 1
  • 1

與Global Indexing不同的是,如果select子句里面帶有除了索引列(USER_NAME)以外的列,仍然可以走索引表。

【說明】

創建Local Indexing時候指定的索引名稱會與實際創建在Hbase里面的表名稱不一致,這應該是Phoenix做了映射的關系,而且對于同一個Hbase里面的table創建多個Local Indexing,索引表在Hbse list命令查詢的時候也只有一個。

5.2 測試案例2

HBase 1e數據?
ammeter_test表

【Global Indexing】

create index AMMETER_TEST_IDXon AMMETER_TEST ("info"."ammeter_no1", "info"."ammeter_no2") include("info"."ammeter_price");
  • 1
  • 2
  • 1
  • 2

(1) 條件查詢包含rowkey

> explain select * from AMMETER_TEST where "info"."ammeter_no1" = '11000000005281' AND "ammeter_no2" = '11000000001004' and ROW = '11000002310462' > select * from AMMETER_TEST where "info"."ammeter_no1" = '11000000005281' AND "ammeter_no2" = '11000000001004' and ROW = '11000002310462'
  • 1
  • 2
  • 1
  • 2

(2) 條件查詢不包含rowkey但滿足二級索引查找條件

> explain select ROW,"ammeter_price" from AMMETER_TEST where "info"."ammeter_no1" = '11000000005281' and "ammeter_no2" = '11000000001004' > select ROW,"ammeter_price" from AMMETER_TEST where "info"."ammeter_no1" = '11000000005281' and "ammeter_no2" = '11000000001004' LIMIT 5
  • 1
  • 2
  • 1
  • 2

【分析】

  • 對于包含rowkey的條件查詢,Phoenix會啟用服務器端過濾器快速篩選匹配的行并返回,億級數據也能達到毫秒級別響應。
  • 對于沒有包含rowkey的條件查詢,如果條件滿足Phoenix二級索引查找,Phoenix會查二級索引表并快速返回記錄。

6. 同步創建索引與異步創建索引

前面所講的創建索引為同步創建索引,當執行create index的時候,索引表會直接與源數據表進行同步。但是,有時候我們的源表數據量很大,同步創建索引會拋出異常。異常信息大致如下所示:

15/12/11 14:20:08 WARN client.ScannerCallable: Ignore, probably already closed org.apache.hadoop.hbase.UnknownScannerException: org.apache.hadoop.hbase.UnknownScannerException: Name: 37, already closed? at org.apache.hadoop.hbase.regionserver.RSRpcServices.scan(RSRpcServices.java:2092) at org.apache.hadoop.hbase.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:31443) at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:2035) at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:107) at org.apache.hadoop.hbase.ipc.RpcExecutor.consumerLoop(RpcExecutor.java:130) at org.apache.hadoop.hbase.ipc.RpcExecutor$1.run(RpcExecutor.java:107) at java.lang.Thread.run(Thread.java:745) at sun.reflect.GeneratedConstructorAccessor13.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:526) at org.apache.hadoop.ipc.RemoteException.instantiateException(RemoteException.java:106) at org.apache.hadoop.ipc.RemoteException.unwrapRemoteException(RemoteException.java:95) at org.apache.hadoop.hbase.protobuf.ProtobufUtil.getRemoteException(ProtobufUtil.java:313) at org.apache.hadoop.hbase.client.ScannerCallable.close(ScannerCallable.java:329) at org.apache.hadoop.hbase.client.ScannerCallable.call(ScannerCallable.java:184) at org.apache.hadoop.hbase.client.ScannerCallableWithReplicas.call(ScannerCallableWithReplicas.java:136) at org.apache.hadoop.hbase.client.ScannerCallableWithReplicas.call(ScannerCallableWithReplicas.java:56) at org.apache.hadoop.hbase.client.RpcRetryingCaller.callWithoutRetries(RpcRetryingCaller.java:200) at org.apache.hadoop.hbase.client.ClientScanner.call(ClientScanner.java:288) at org.apache.hadoop.hbase.client.ClientScanner.close(ClientScanner.java:507) at org.apache.phoenix.iterate.ScanningResultIterator.close(ScanningResultIterator.java:49) at org.apache.phoenix.iterate.TableResultIterator.close(TableResultIterator.java:95) at org.apache.phoenix.jdbc.PhoenixResultSet.close(PhoenixResultSet.java:162) at org.apache.phoenix.compile.UpsertCompiler.upsertSelect(UpsertCompiler.java:199) at org.apache.phoenix.compile.UpsertCompiler.access$000(UpsertCompiler.java:114) at org.apache.phoenix.compile.UpsertCompiler$UpsertingParallelIteratorFactory.mutate(UpsertCompiler.java:229) at org.apache.phoenix.compile.MutatingParallelIteratorFactory.newIterator(MutatingParallelIteratorFactory.java:62) at org.apache.phoenix.iterate.ParallelIterators$1.call(ParallelIterators.java:109) at org.apache.phoenix.iterate.ParallelIterators$1.call(ParallelIterators.java:100) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at org.apache.phoenix.job.JobManager$InstrumentedJobFutureTask.run(JobManager.java:183) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caused by: org.apache.hadoop.hbase.ipc.RemoteWithExtrasException(org.apache.hadoop.hbase.UnknownScannerException): org.apache.hadoop.hbase.UnknownScannerException: Name: 37, already closed? at org.apache.hadoop.hbase.regionserver.RSRpcServices.scan(RSRpcServices.java:2092) at org.apache.hadoop.hbase.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:31443) at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:2035) at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:107) at org.apache.hadoop.hbase.ipc.RpcExecutor.consumerLoop(RpcExecutor.java:130) at org.apache.hadoop.hbase.ipc.RpcExecutor$1.run(RpcExecutor.java:107) at java.lang.Thread.run(Thread.java:745) at org.apache.hadoop.hbase.ipc.RpcClientImpl.call(RpcClientImpl.java:1199) at org.apache.hadoop.hbase.ipc.AbstractRpcClient.callBlockingMethod(AbstractRpcClient.java:216) at org.apache.hadoop.hbase.ipc.AbstractRpcClient$BlockingRpcChannelImplementation.callBlockingMethod(AbstractRpcClient.java:300) at org.apache.hadoop.hbase.protobuf.generated.ClientProtos$ClientService$BlockingStub.scan(ClientProtos.java:31889) at org.apache.hadoop.hbase.client.ScannerCallable.close(ScannerCallable.java:327) ... 20 more
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

這個時候,我們可以采用異步創建索引,方式如下:

CREATE INDEX async_index ON my_schema.my_table (v) ASYNC
  • 1
  • 1

通過create index的時候指定?ASYNC?關鍵字來指定異步創建索引。執行這個命令之后并不會引起索引表與源表的直接同步。這個時候查詢并不會使用這個索引表。那么索引數據的導入還需要采用phoenix提供的索引同步工具類?IndexTool?, 這是一個mapreduce工具類,使用方式如下:

${HBASE_HOME}/bin/hbase org.apache.phoenix.mapreduce.index.IndexTool--schema MY_SCHEMA --data-table MY_TABLE --index-table ASYNC_IDX--output-path ASYNC_IDX_HFILES
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

當mapreduce任務執行結束,這個索引表才會變成可用。

7. 參考

(1)?可變索引與不可變索引

(2)?Globaling Indexing

(3)?Local Indexing

(4)?配置二級索引及測試

(5)?Phoenix官網文檔

總結

以上是生活随笔為你收集整理的HBase phoenix二级索引的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。