云原生多模數據庫Lindorm的主鍵HASH打散功能是指通過HASH函數將數據分散到不同的分片(Region),實現數據的分布式存儲和查詢,避免數據傾斜和負載不均等問題。本文介紹主鍵HASH打散功能的使用方法。
背景信息
Lindorm寬表引擎是基于Range分區的分布式存儲引擎。通常情況下,寫入Lindorm寬表引擎的數據會均勻地分布在不同的分片中。
在實際使用過程中,如果流量分布不均勻,例如訪問某些數據的頻率明顯高于其他數據,則可能會導致數據在分片上的分布不均衡進而產生熱點問題,無法充分利用分布式系統的優勢。此時,您可以通過調整訪問方式解決數據分布問題。但如果該問題是由于主鍵以某種規則生成,無法打散(例如自增主鍵或格式為HH:mm:ss
的時間列),推薦您使用主鍵HASH打散功能。
主鍵HASH打散功能可以將上述無法打散的數據均勻地分散到不同的分片,提升系統的可擴展性。同時,支持在Range分區的基礎上執行分布式查詢,提高查詢效率。
如果您的業務場景符合以上適用場景,那么在建表或創建二級索引時對指定主鍵列使用HASH算法,即可實現數據打散。
前提條件
注意事項
在主鍵列或索引中對指定列使用HASH算法時,HASH函數表達式必須放在最前面。例如錯誤用法為
PRIMARY KEY( p1, hash32(p1),p2)
,正確的用法為PRIMARY KEY(hash32(p1), p1, p2)
。在主鍵列或索引中對某列使用HASH算法時,必須指定該列為主鍵列或索引列。
已指定HASH算法的主鍵列不支持修改。
使用主鍵HASH打散功能后,不支持使用bulkload方式導入數據。
DDL
建表
建表時,在PRIMARY KEY中設置主鍵列,并對指定主鍵列使用HASH算法。目前支持8位、32位和64位HASH算法。您可以根據主鍵的特點,對任意一個或多個主鍵列使用不同的HASH算法。
HASH算法的位數越大,存儲底層消耗的內存越多,存儲成本越大。例如,采用32位HASH算法時,存儲底層每對keyValue將額外消耗4 Bytes。
示例如下:
# 對一個主鍵列使用HASH算法
CREATE TABLE t1 (
p1 bigint,
p2 integer,
c1 integer,
c2 varchar,
PRIMARY KEY(hash32(p1), p1, p2)
);
# 對多個主鍵列使用HASH算法
CREATE TABLE t2 (
p1 bigint,
p2 integer,
c1 integer,
c2 varchar,
PRIMARY KEY(hash8(p1, p2), p1, p2)
);
hash32(p1)
表示對p1列使用32位HASH算法;hash8(p1, p2)
表示同時對p1列和p2列使用8位HASH算法。
建二級索引
支持對索引表使用主鍵HASH打散功能。
如果在創建主表時已對指定列使用HASH算法,但在建二級索引時未對指定列使用HASH算法,則索引表默認不會打散數據。
CREATE INDEX idx ON t1 (hash64(c1, c2), c1, c2);
查看HASH列詳情
您可以查看表結構來查看HASH列詳情。
DESCRIBE table t1;
返回結果:
+--------------+------------+-------------+---------+----------------+------------+
| TABLE_SCHEMA | TABLE_NAME | COLUMN_NAME | TYPE | IS_PRIMARY_KEY | SORT_ORDER |
+--------------+------------+-------------+---------+----------------+------------+
| test1 | t1 | hash32[p1] | INT | true | ASC |
| test1 | t1 | p1 | BIGINT | true | ASC |
| test1 | t1 | p2 | INT | true | ASC |
| test1 | t1 | c1 | INT | false | none |
| test1 | t1 | c2 | VARCHAR | false | none |
+--------------+------------+-------------+---------+----------------+------------+
DML
數據寫入
寫入數據時,無需在SQL語句中添加HASH相關參數,系統將根據寫入的數據自動生成并填充HASH值。
UPSERT INTO t1(p1, p2, c1, c2) VALUES(1, 1, 1, 'a');
數據查詢
查詢數據時,無需在SQL語句中添加HASH相關參數,系統將自動根據查詢條件計算HASH值。但需要注意以下兩點:
必須指定所有已使用HASH算法的主鍵列的值。否則系統會因為列缺省而無法計算HASH值,導致無法定位到數據所在的分片從而查詢全表。
以t1表為例,查詢示例如下:
# 推薦的使用方式 SELECT * FROM t1 WHERE p1=1 AND p2=1; # 系統將查詢hash(p1)=hash32(1)的分片 # 不推薦的使用方式 SELECT * FROM t1 WHERE p2=1; # 未指定主鍵列p1的值,會導致系統無法定位至HASH值對應的分片進而查詢全表
對于使用了HASH算法的主鍵列,查詢條件必須為等值查詢,例如
p1=2
,不支持HASH列的范圍查詢,例如p1>1
。以t1表為例,查詢示例如下:
# 正確使用方式 SELECT * FROM t1 WHERE p1=2 AND p2>1; # 錯誤使用方式 SELECT * FROM t1 WHERE p2=1 AND p1>2 AND p1<8; # 不支持此查詢方式(主鍵列p1設置為范圍查詢)
如需查看SELECT語句的執行情況,請參見EXPLAIN。