全部產品
Search
文件中心

PolarDB:STR_HASH

更新時間:Jul 06, 2024

本文將介紹STR_HASH函數使用方式。

注意事項

使用STR_HASH做拆分的表僅適用於點查情境,如果在業務中範圍查詢,則會接直接觸發全表掃描導致慢查詢。

使用限制

  • 拆分鍵的資料類型需為字串類型(CHAR或VARCHAR)。
  • 不支援在建表完成後再調整STR_HASH的參數。
  • PolarDB-X 1.0的執行個體版本需為5.3.5或以上

使用情境

  • 實現一個分表(或分庫)只對應一個拆分表鍵的取值(字串類型)的精準路由效果。

    例如,某個互連網金融應用是按年月(YYYYMM)分庫,然後按訂單號分表,該應用的訂單號有個特點,就是訂單號的最後3位字串是一個整數,其取值範圍是000~999。該應用的需求是需要在一個物理分庫內,要將訂單號後3位的每一個數值只單獨路由到一個物理分表。那麼,該應用分庫採用YYYYMM,然後分表採用拆分函數STR_HASH,每個庫1024個分表,就可以達到效果。具體的SQL語句如下:

    create table test_str_hash_tb (    
        id int NOT NULL AUTO_INCREMENT,
        order_id varchar(30) NOT NULL, 
        create_time datetime DEFAULT NULL,
        primary key(id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 
    dbpartition by YYYYMM(`create_time`) 
    tbpartition by STR_HASH(`order_id`, -1, 3, 1) tbpartitions 1024;

    應用採用這樣建表SQL,原因是分表的字串截取後3位並轉換為整數(整數範圍是000~999)後再模數做分表路由(共1024個分表),其路由結果能保證每一個物理分表只對一個拆分建的取值。而原來預設拆分函數HASH無法達到這樣的效果,是因為字串經過hashCode計算後的整數是不可預知的,有可能會出現一個物理分表要對應多個不同拆分建的取值。

  • 典型的點查情境

    STR_HASH拆分函數適用於使用字串類型作為拆分鍵並且是絕大部分都是點查的情境,如根據ID查交易訂單、物流訂單等。

函數定義

STR_HASH函數通過指定字串的開始位置下標與結束下標,以截取拆分鍵的字串的某段子串,然後將其作為字串(或整數)輸入進行分庫分表的路由計算,計算具體的物理分區,具體函數如下所示:

STR_HASH( shardKey [, startIndex, endIndex [, valType [, randSeed ] ] ] )
表 1. 參數說明
參數說明
shardKey拆分鍵列的列名。
startIndex目標子串的開始位置的下標。取值從0開始(即原字串的第1個字元的下標用0表示),預設值為-1(即不做任何截取)。
endIndex目標子串的結束位置的下標。取值從0開始(即原字串的第1個字元的下標用0表示),預設值為-1(即不做任何截取)。
說明 startIndexendIndex時需注意如下幾種取值情況:
  • startIndex == j && endIndex = k (j>=0, k>=0 ,k>j)時,表示截取原字串的[ j, k )區間的字串作為子串。例如:
    • 對於字串ABCDEFG,子串區間[1,5)的值是BCDE
    • 對於字串ABCDEFG,,子串區間[2,2)的值是''
    • 對於字串ABCDEFG,子串區間[4,100)的值是EFG
    • 對於字串 ABCDEFG,子串區間[100,105)的值是''
  • startIndex == -1 && endIndex = k (k>=0)時,表示截取原字串最後k個字元作為子串,原字串不足k個字元則直接擷取整個字串。
  • startIndex = k && endIndex == -1 (k>=0)時,表示截取原字串開頭k個字元作為子串,原字串不足k個字元則直接擷取整個字串。
  • startIndex == -1 && endIndex == -1時, 表示不做任何截取,子串與原字串完全一致。
valType表示截取後的子串在計算分庫分表時所使用的類型,取值範圍如下:
  • 0(預設值):表示PolarDB-X 1.0將截取後的子串當作字串類型來計算路由。
  • 1:表示PolarDB-X 1.0將截取後的子串當作整數類型來計算路由(子串面值的整數不能大於9223372036854775807,也不支援浮點數
randSeed當子串以字串類型來計算路由的雜湊值時PolarDB-X 1.0所使用的隨機種子的值,通常不用需要填寫,僅當用於使用預設值隨機種子(randSeed=31)的STR_HASH在實際業務中出現路由不均衡的情境,達到用雜湊均衡資料的目的。該參數預設值為31,可取其他值(如131,13131,1313131等)。
說明
  • 僅當valType取值為0時,才支援配置該參數。
  • 該參數調整後您需要手動將所有資料匯出來,再將新的拆分演算法匯入資料(即您需要對資料進行重分布)。

使用樣本

假設order_id的類型為VARCHAR(32),現在需要將order_id作為拆分鍵,計劃分4個庫,分8個表。

  • 假設需要使用order_id的最後4位的字串作為整數來計算分庫分表路由,則您可以使用如下SQL進行建表。
    create table test_str_hash_tb (    
        id int NOT NULL AUTO_INCREMENT,
        order_id varchar(32) NOT NULL, 
        create_time datetime DEFAULT NULL,
        primary key(id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 
    dbpartition by STR_HASH(`order_id`, -1, 4, 1) 
    tbpartition by STR_HASH(`order_id`, -1, 4, 1) tbpartitions 2;
  • 假設需要截取order_id的第3個字元(即starIndex=2)與第7個字元(即endIndex=7)之間子串來計算分庫分表路由,則您可以使用如SQL進行建表。
    create table test_str_hash_tb (    
        id int NOT NULL AUTO_INCREMENT,
        order_id varchar(32) NOT NULL, 
        create_time datetime DEFAULT NULL,
        primary key(id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 
    dbpartition by STR_HASH(`order_id`, 2, 7) 
    tbpartition by STR_HASH(`order_id`, 2, 7) tbpartitions 2;
  • 假設需要截取order_id的前5個字串作為子串來計算分庫分表路由,則您可以使用如SQL進行建表。
    create table test_str_hash_tb (    
        id int NOT NULL AUTO_INCREMENT,
        order_id varchar(32) NOT NULL, 
        create_time datetime DEFAULT NULL,
        primary key(id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 
    dbpartition by STR_HASH(`order_id`, 5, -1) 
    tbpartition by STR_HASH(`order_id`, 5, -1) tbpartitions 2;

常見問題

Q:dbpartition by STR_HASH(order\_id)dbpartition by HASH(order\_id)有什麼區別?

A:兩者雖然都是直接根據字串取值做分庫分表的雜湊路由,但是兩者的分庫分表的路由演算法實現不一樣。前者支援使用者建表時自行設定截取子串相關參數,且在根據字串的雜湊值計算分庫分表路由時是基於UNI_HASH演算法進行計算;而後者是只對字串的雜湊值做簡單模數。