phoenix全域性索引和本地索引 概述,使用場景,區別等詳解

小哇666發表於2020-10-07

索引型別

phoenix的索引大致分為兩類global index和local index,好像和星環有點類似,其實這是hbase二級索引解決方案裡面廣為人知的兩種方案,側重點不同,使用場景也不一樣。

  • global index,global是預設的索引格式。官方文件翻譯過來的:Global indexing適用於多讀少寫的業務場景。使用Global indexing的話在寫資料的時候會消耗大量開銷,因為所有對資料表的更新操作(DELETE, UPSERT VALUES and UPSERT SELECT),會引起索引表的更新,而索引表是分佈在不同的資料節點上的,跨節點的資料傳輸帶來了較大的效能消耗。在讀資料的時候Phoenix會選擇索引表來降低查詢消耗的時間。在預設情況下如果想查詢的欄位不是索引欄位的話索引表不會被使用,也就是說不會帶來查詢速度的提升。
  • Local index,適用於寫操作頻繁的場景。與Global index一樣,Phoenix會自動判定在進行查詢的時候是否使用索引。使用Local indexing時,索引資料和資料表的資料是存放在相同的伺服器中的避免了在寫操作的時候往不同伺服器的索引表中寫索引帶來的額外開銷。使用Local indexing的時候即使查詢的欄位不是索引欄位索引表也會被使用,這會帶來查詢速度的提升,這點跟Global indexing不同。一個資料表的所有索引資料都儲存在一個單一的獨立的可共享的表中。

官方文件上寫的太書面了,下面用幾個例子就能明白這兩種索引格式是怎麼設計以及怎樣執行原理了。

全域性索引 測試 

//建立鹽表,就是預分割槽表的一種
create table ns1.testsalt 
(id integer primary key, 
name varchar,
age integer,
address varchar) 
salt_buckets = 6;

//新增資料
upsert into ns1.testsalt (id,name,age,address) values(1,'zhangshan',18,'chongqing');
upsert into ns1.testsalt (id,name,age,address) values(2,'lishi',16,'wuhan');

//建立索引
CREATE  INDEX testsalt_idx ON  ns1.testsalt(name,age);
CREATE  INDEX testsalt_idx_2 ON  ns1.testsalt(name,age) include(address);

//刪除索引
DROP    INDEX testsalt_idx ON  ns1.testsalt;

//phoenix中查詢表和索引表的資料
select * from ns1.testsalt;
select * from ns1.testsalt_idx;
select * from ns1.testsalt_idx_2;

//explain檢視sql執行情況
explain select address from ns1.testsalt where age=17;

//強制走索引
explain select /*+ INDEX(ns1.testsalt testsalt_idx) */ address from ns1.testsalt where age=17;

//hbase中查詢表和索引表的資料
scan 'NS1:TESTSALT'
scan 'NS1:TESTSALT_IDX'
scan 'NS1:TESTSALT_IDX_2'

全域性索引
1.以上可以看出global index的設計方式,會單獨寫一張索引表,列族為include欄位,rowkey的設計方位是:
二級索引欄位1+"\x00"+二級索引欄位2(複合索引)…+"\x00"+原表rowkey
2.查詢的時候,會直接定位到索引表,通過rowkey查到位置,然後從索引表中帶出資料
3.因為建立索引的時候還要多寫一份include欄位,讀的時候直接從索引表定位並讀出資訊。所以這種表的應用場景定位是寫的慢,讀得快


本地索引 測試

//建立表
create table ns1.testlocal 
(id integer primary key, 
name varchar,
age integer,
address varchar);

//新增資料
upsert into ns1.testlocal (id,name,age,address) values(1,'wangwu',21,'shandong');
upsert into ns1.testlocal (id,name,age,address) values(2,'chenmazi',26,'xinjiang');

//建立索引,注意關鍵詞 local
CREATE local INDEX testlocal_idx ON  ns1.testlocal(name,age);
CREATE local INDEX testlocal_idx_2 ON  ns1.testlocal(name,age) include(address);

//刪除索引
DROP   INDEX testlocal_idx ON  ns1.testlocal;

//phoenix中查詢表和索引表的資料
select * from ns1.testlocal;
select * from ns1.testlocal_idx;
select * from ns1.testlocal_idx_2;

//explain檢視sql執行的情況
explain select address from ns1.testlocal where age=17;

//強制走索引
explain select /*+ INDEX(ns1.testlocal testlocal_idx) */ address from ns1.testlocal where age=17;

//hbase中查詢表
scan 'NS1:TESTLOCAL'

本地索引
1.以上可以看出local index的設計方式,索引資料直接寫在原表rowkey中,列族不寫任何實際資訊,local index的rowkey的設計方位是:
原資料region的start key+"\x00"+二級索引欄位1+"\x00"+二級索引欄位2(複合索引)…+"\x00"+原rowkey
第一條資訊"原資料region的start key",這樣做的目的是保證索引資料和原資料在一個region上,定位到二級索引後根據原rowkey就可以很快在本region上獲取到其它資訊,減少網路開銷和檢索成本。
2.查詢的時候,會在不同的region裡面分別對二級索引欄位定位,查到原rowkey後在本region上獲取到其它資訊
3.因為這種索引設計方式只寫索引資料,省了不少空間的佔用,根據索引資訊拿到原rowkey後再根據rowkey到原資料裡面獲取其它資訊。所以這種表的應用場景定位是寫的快,讀得慢 
 

不管是全域性索引 ,還是本地索引,從phoenix查詢,索引也是一張表,如下圖所示

 

全域性索引,本地索引不同點 和 比較
直白話:全域性索引是表,適合重讀輕寫的場景 ,
               本地索引是列族,適合重寫輕讀的場景

1.索引資料

  • global index單獨把索引資料存到一張表裡,保證了原始資料的安全,侵入性小
  • local index把資料寫到原始資料裡面,侵入性強,原表的資料量=原始資料+索引資料,使原始資料更大

2.效能方面

  • global index要多寫出來一份資料,寫的壓力就大一點,但讀的速度就非常快
  • local index只用寫一份索引資料,節省不少空間,但多了一步通過rowkey查詢資料,寫的速度非常快讀的速度就沒有直接取自己的列族資料快

 

相關文章