date: 2020-09-10 13:50:00
updated: 2020-09-14 16:30:00
1. Phoenix索引
全局索引:適合讀多寫少的場景。寫數據時因為索引表分布在不同數據節點,跨節點數據傳輸帶來巨大的性能消耗。
全局索引必須是查詢語句中所有列都包含在全局索引中,它才會生效。
create index my_index on my_table (v3);
select v1 from my_table where v3 = '13406157616';
此時不會走索引,因為檢索列不在全局索引中,有以下三種方法使它使用索引:
1. 使用覆蓋索引
CREATE INDEX cover_index ON my_table(v3) INCLUDE (v1);
2. 使用 Hint 強制索引
SELECT /*+ INDEX(my_table my_index) */ v1 FROM my_table WHERE v3 = '13406157616';
3. 使用本地索引
CREATE LOCAL INDEX local_index on my_table (v3);
本地索引:適合讀少寫多的場景。在本地生成一個索引表。
覆蓋索引:配合全局索引使用,避免回表查詢。
函數索引:適合拼接式字符串查詢?。
創建索引的時候有可能因為表的數據量過大,導致索引表的數據量過大,導致發生超時異常,創建出來的索引表不完整,此時可以通過異步索引創建來解決 -- 在創建索引的語句最后添加一個 async,執行語句會直接返回結果,但是索引表狀態是處于building。
每一個put/delete操作執行前,會先寫入到主表的 Write Ahead Log (WAL) 中,如果出現HBase服務器宕機,則可以從WAL中回放執行之前沒有完成的操作,用來保證高并發、持久化的日志保存與回放機制。因為索引表的更新可能會落后于主表一小部分。
WAL日志文件使用的是Hadoop Sequence文件格式,其主要特點:
二進制格式。row key, family, qualifier, timestamp, value等HBase byte[]數據,都原封不動地順序寫入文件。
Sequence文件中,每隔若干行,會插入一個16字節的魔數作為分隔符。這樣如果文件損壞,導致某一行殘缺不全,可以通過這個魔數分隔符跳過這一行,繼續讀取下一個完整的行。
支持壓縮。可以按行壓縮。也可以按塊壓縮(將多行打成一個塊)
2. Phoenix加鹽
加鹽的目的是為了讓數據分散到不同機器,緩解查詢壓力
如果行鍵即數據,單調增加,那么數據會分布在一個region里,可能會造成熱點問題 => 通過添加 SALT_BUCKETS = Num(0 -- 256) 來對行鍵添加一個字節,使得數據能更均勻分布到各個region中。
其中0是關閉對數據表添加了鹽分的索引的鹽析的一種特殊方式(因為默認情況下,索引與其數據表具有相同數量的鹽桶)
由于加鹽表不會順序存儲數據,因此嚴格的順序掃描不會以自然排序的方式返回所有數據。強制進行順序掃描的子句(例如帶有LIMIT的子句)可能會返回與普通表不同的數據順序。
new_row_key = (++index % BUCKETS_NUMBER) + original_key
3. 主鍵查詢
通過關鍵字 !primarykeys table 或者下面這段查詢
select
TENANT_ID TABLE_CAT,TABLE_SCHEM,TABLE_NAME ,COLUMN_NAME,KEY_SEQ,PK_NAME,CASE WHEN SORT_ORDER = 1 THEN 'D' ELSE 'A' END ASC_OR_DESC,ExternalSqlTypeId(DATA_TYPE) AS DATA_TYPE,SqlTypeName(DATA_TYPE) AS TYPE_NAME,COLUMN_SIZE,DATA_TYPE TYPE_ID,VIEW_CONSTANT from SYSTEM."CATALOG" "SYSTEM.TABLE" where
TABLE_SCHEM = 'MODEL_GROUP_RULE_ACCOUNT_TEST'
and TABLE_NAME = 'ECEJ_CALLING_CENTER_H'
and COLUMN_NAME is not null
and COLUMN_FAMILY is null
order by TENANT_ID,TABLE_SCHEM,TABLE_NAME ,COLUMN_NAME
4. 修改字段長度
當創建好phoenix的表后, 默認情況下phoenix不允許修改字段類型和長度。但是可以通過直接修改 SYSTEM.CATALOG 里的數據達到目的
upsert into SYSTEM.CATALOG (TENANT_ID,TABLE_SCHEM,TABLE_NAME,COLUMN_NAME,COLUMN_FAMILY,DATA_TYPE,COLUMN_SIZE) values('','庫','表','字段','0',12,50);
測試發現,即使上面的上SQL執行成功,重新執行 upsert 往表里插入數據,DEBIT_AMOUNT(初始長度6)超過初始長度的還是不能成功
經過查看源碼發現,在 SYSTEM.CATALOG 上有協處理器, 這個里面有表元數據緩存,默認要三個小時過期
org.apache.phoenix.cache.GlobalCache
long maxTTL = this.config.getLong("phoenix.coprocessor.maxMetaDataCacheTimeToLiveMs", 1800000L);
long maxSize = this.config.getLong("phoenix.coprocessor.maxMetaDataCacheSize", 20971520L);
猜想修改長度后三小時能生效
或者在hbase shell 中 先 disable SYSTEM.CATALOG, 然后在 enable SYSTEM.CATALOG